From dd2d3c17e1a01a2f0ada708a0ce2c86f515f0e05 Mon Sep 17 00:00:00 2001 From: 6r1d Date: Sun, 16 Feb 2025 02:11:17 +0200 Subject: [PATCH] [article]: Tri-eulogy series (unfinished) --- build-site.el | 17 +- docs/brittle-supply-chains.org | 179 ++++++++++++ docs/index.org | 6 + docs/kill-the-ads-save-the-planet.org | 2 +- docs/style1.css | 17 +- docs/the-myth-of-the-users-journey.org | 319 +++++++++++++++++++++ docs/xkcd_dependency.js | 83 ++++++ docs/xkcd_dependency.json | 368 +++++++++++++++++++++++++ 8 files changed, 985 insertions(+), 6 deletions(-) create mode 100644 docs/brittle-supply-chains.org create mode 100644 docs/the-myth-of-the-users-journey.org create mode 100644 docs/xkcd_dependency.js create mode 100644 docs/xkcd_dependency.json diff --git a/build-site.el b/build-site.el index fc1bb00..e7405c2 100644 --- a/build-site.el +++ b/build-site.el @@ -28,12 +28,21 @@ :email "ap886@cantab.ac.uk" :html5-fancy t :with-email t - :auto-sitemap t))) + :auto-sitemap t) + (list "my-org-site-static" + :recursive t + :base-directory "./res" + :base-extension "png\\|jpg\\|jpeg\\|gif\\|svg\\|webp" + :publishing-directory "./public/res" + :publishing-function 'org-publish-attachment))) (setq org-html-validation-link nil) (defconst stylesheet "style1.css") (defconst main_js "main.js") +(defconst xkcd_dependency_json "xkcd_dependency.json") +(defconst xkcd_dependency_js "xkcd_dependency.js") + ;; Custom appearance (setq org-html-validation-link nil ;; Don't show validation link org-html-head-include-scripts t ;; Use our own scripts @@ -43,12 +52,12 @@ ;; Generate the site output (org-publish-all t) - - ;; Copy local css and JS (message (format "Copying CSS ./docs/%s" stylesheet)) (copy-file (format "./docs/%s"stylesheet) "./public/" t nil nil nil) -(message (format "Copying JS ./docs/%s" main_js)) +(message (format "Copying JS & JSON ./docs/%s" main_js)) (copy-file (format "./docs/%s"main_js) "./public/" t nil nil nil) +(copy-file (format "./docs/%s"xkcd_dependency_json) "./public/" t nil nil nil) +(copy-file (format "./docs/%s"xkcd_dependency_js) "./public/" t nil nil nil) (message "Build complete") diff --git a/docs/brittle-supply-chains.org b/docs/brittle-supply-chains.org new file mode 100644 index 0000000..65d69b3 --- /dev/null +++ b/docs/brittle-supply-chains.org @@ -0,0 +1,179 @@ +#+title: Brittle supply chains +#+AUTHOR: Viktor Gridnevsky, Aleksandr Petrosyan and friends +#+DATE: 16.02.2025 +#+LANGUAGE: en_GB +#+OPTIONS: toc:nil # Disable automatic TOC + +#+BEGIN_EXPORT html +
+ +#+END_EXPORT + +#+TOC: headlines 2 + +There are many situations in which code updates are necessary, from operating system +packages to changes in company infrastructure. Updates that break code +can be expensive, costing not just money but also time and effort to fix. +There's a domino effect in all that: when one dependency fails, +it can take down many other dependencies with it, ending with specific programs. +Our traditional strategies for preventing relevant failures are +increasingly incompatible with today’s traditionally layered and interdependent designs. + +The “Literate programming” paradigm proposed by Donald Knuth in 1980s +makes code easier to understand by interweaving code and documentation. +Newer approaches following it focus on keeping things simple, clear, and efficient. +Yet, even the cleanest code is not safe from the cascading failures +when it depends on an unpredictable stack of third-party components +that can change unpredictably and are created by strangers with varying priorities. +My personal belief is that if a dependency cannot be relied upon +to change in a predictable way, it should not be part of the foundation. + +More fundamental solutions with formal verification and mathematical proofs, +as seen in projects like seL4 and Coq, already exist, +but ensuring correctness doesn't match the typical development workflow we see nowadays. +Balancing formal verification with evolving requirements, rapid prototyping, +market responsiveness, and backward compatibility would create unrealistic amounts of work. +At the same time, should we examine the current development situation through a proof by contradiction, +we must question whether the current workflow and its underlying assumptions +deserve the level of importance they are given or if they should instead be critically reassessed. +This workflow did not emerge as an optimal, deliberate design but rather as a historical accident, +shaped by shifting market pressures, time constraints, and the inertia of legacy practices. +It is not inherently the most reliable or effective, nor does it minimize technical debt. +In fact, it often exacerbates it. +Furthermore, the notion of "best practices" within this system is fragmented at best. +Many developers neither follow nor agree on a singular, cohesive set of principles, +leading to inconsistent quality, inefficiencies, and further unpredictability. + +Another way to handle broken software is through compatibility layers[fn:1]. +Things I’ll put in that category include Java, other Just-In-Time (JIT) compilers, +and Wine, which lets Windows programs run on other systems. +Containers, be it Docker or Podman, with or without Kubernetes, +provide yet another tool in that arsenal. +Yet, if an underlying dependency breaks, the compatibility layer can fail just as easily, +taking everything that depends on it with it. +These layers don’t eliminate supply chain risks and usually are not built with that as a key goal in mind; +they are just another link in the dependency chain, vulnerable to the same breakages they aim to mitigate. + +Despite decades of progress, our solutions are still scattered and limited. +The more I code, the more I see how much we rely on high-level abstractions, +which are often related to the peculiar kind I have mentioned in “product thinking”. + +I would expect a stable development ecosystem would be ensuring the developers +know what changes, what remains, and how to adapt. +I would expect a stable development ecosystem would require a structured method, +clear metadata in the repository and changes in development software to +track, version, and notify developers of dependency changes in an automated, +predictable way. +But it's not where we are. + +I don’t have all the answers, and I’m not claiming to, yet, +I can start by asking the right questions. + +** The software entropy +:PROPERTIES: +:CUSTOM_ID: the-software-entropy +:END: +We rely on many software systems daily, expecting them to be stable. +Testing is costly and only a few systems have reliable test coverage. +Even fewer are rigorously tested with tools like theorem provers[fn:2]. +When we create new software, we often fail to document what mechanisms +it relies on. In turn, that forces the users to guess these mechanisms +using indirect evidence. This can be a lot of work, even when developers +think it's obvious. + +Many systems are *called* "production-ready" even when their +abstractions leak in "irrelevant places". The complexity of such +software is hidden, the internal mechanisms are inaccessible, logic is +obscured. Decision-making happens beneath the surface. That limits the +amount of people able to improve their understanding of the software. +People can't easily trace how the inputs of that software become +outputs. Instead of true understanding, we, as users, are often forced +to interact with black boxes, rely on heuristics, *trial-and-error +debugging*, or external docs. I've been told this kind of unclarity is +called *epistemic opacity*. Why is *epistemic opacity* a problem? Well, +it stops us from forming accurate mental models of the behavior for +systems we work with, independently verifying them and independently +reasoning about them. Essentially, it stops us from understanding and +using that understanding effectively, making us rely on authority +figures[fn:3]. + +Speaking of our understanding of the software, configuration is just as +important. But how clearly can we configure a system when its logic is +unclear? When settings aren't tied to well-understood mechanisms, +configurations become unstable. This is *configuration fragility*. + +Without a clear mental model, small changes can cause big, unpredictable +problems, which leads to *emergent failures*, which, in turn, are hard +to diagnose and fix. The problem gets worse with *black-box dependency*, +where the system's inner workings are hidden. Modern software supply +chains are long. Users operate on incomplete assumptions. Configurations +become *arbitrary incantations*, not meaningful mappings. The lack of +transparency forces *trial-and-error debugging*. It reduces proactive +problem-solving. It increases systemic brittleness. Configurations work +under normal conditions but fail under stress. Instead of *predictable +adaptability*, these systems create operational overhead. Maintenance +gets harder. Iteration and optimization are blocked. + +*** Example: the banking software +:PROPERTIES: +:CUSTOM_ID: example-the-banking-software +:END: +Think about the systems we need to live, work, and be part of society. +Banking technologies are a good example. They've become near-untouchable +due to their role, but the aspect of things growing out of proportion +due to the society's reliance on them is a different topic. Some say +banks are a "convenience", not a necessity. Well, everyone has reasons +to use these services. Try avoiding them when buying electronic parts +from China to study electronics. I depend on the stability of banks, +yet, they are opaque and unverifiable. For many reasons, the bank +software is closed-source. Independent verification or auditing is +impossible. All the while, the users have no practical alternative. We +rely on systems we can't check for reliability, security, or logic. This +lack of transparency reinforces the *epistemic opacity*. It creates +dependency on unverified, inaccessible mechanisms that shape our daily +lives. There's no easy solution, but it's a clear example of the +problem. + +*** Learning, not burning +:PROPERTIES: +:CUSTOM_ID: learning-not-burning +:END: +Historically, my negative experiences that inspired this article come +from dealing with many kinds of software. I picked banks to criticize, +as due to their sheer size, it feels impersonal. While asking the +opinions of the programmers to write this article, it feels like I am +seen as an inquisitor making people uncomfortable. Sometimes, one side +is unhappy with the code the other side writes. Sometimes, the +unhappiness is mutual. + +Let me be clear: this article is about the philosophical and engineering +aspects of software development. Please do not see it as a justification +to point fingers or start a witch hunt. We all all humans and all of us +sometimes make bad decisions, so let's avoid blaming each other on a +personal level. Let's track the problems we face, analyse them and make +our conclusions. Let's learn to build better software. + +*** The elusive source code +:PROPERTIES: +:CUSTOM_ID: the-elusive-source-code +:END: +Let me be clear on another point. Source code isn't always the key to +understanding. It can change so much that it becomes useless. Imagine +legal and medical jargon hidden in open-source software. Most people +would struggle to find the real meaning. Even if they did, they'd have +to explain it to others. If the jargon must stay, someone would need to +translate it regularly. That's rarely realistic. Without this effort, +the source code becomes useless. And that's just semantics. Syntax, +patterns, and other details also affect readability, for better or +worse. Source code alone doesn't solve *epistemic opacity*. + +*TO BE CONTINUED* + +[fn:1] The "compatibility layers" themselves naturally have dependencies. + +[fn:2] =TODO=: add network protocols verified with CoQ later + +[fn:3] It must be noted that often enough, "authority figures" won't + have time to reply or explain their decisions, leaving people who + could've done something useful with no means to improve their + understanding. \ No newline at end of file diff --git a/docs/index.org b/docs/index.org index 97468a5..77a5019 100644 --- a/docs/index.org +++ b/docs/index.org @@ -4,6 +4,12 @@ #+LANGUAGE: en_GB #+OPTIONS: toc:nil +** Feb 2025 + +- Tri-eulogy: [[./the-myth-of-the-users-journey.org][The myth of the “user’s journey”]] +- Tri-eulogy: Product thinking (TBD, still cleaning up the text) +- Tri-eulogy: [[./brittle-supply-chains.org][Brittle Supply Chains]] (TBD, currently collecting comments) + ** Jan 2025 - [[./para-content.org][Paracontent]] - [[./normalised-madness.org][Normalised chaos]] diff --git a/docs/kill-the-ads-save-the-planet.org b/docs/kill-the-ads-save-the-planet.org index d68865d..6f13a79 100644 --- a/docs/kill-the-ads-save-the-planet.org +++ b/docs/kill-the-ads-save-the-planet.org @@ -14,7 +14,7 @@ Syme) from the official CyberLounge Odysee. :CUSTOM_ID: introduction :END: -[[/res/img/Chris_Abney__area_covered_with_green_leafed_plants.jpg]] +#+HTML: Image You went down the internet privacy rabbit hole. You've got [[https://github.com/gorhill/uBlock/][uBlock]], you installed diff --git a/docs/style1.css b/docs/style1.css index 321eb10..26371fd 100644 --- a/docs/style1.css +++ b/docs/style1.css @@ -87,7 +87,7 @@ img { blockquote { - font-family: "Ubuntu" + font-family: "Ubuntu"; max-width: 40em; line-height: 1.4; position: relative; @@ -194,3 +194,18 @@ blockquote:after { background-color: #1c282c; color: #eee; } + +/* + * An interactive block. + * Currently intended for the "supply chains" article. + */ +#interactive-block { + display: flex; + justify-content: center; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + width: 100%; + height: auto; +} diff --git a/docs/the-myth-of-the-users-journey.org b/docs/the-myth-of-the-users-journey.org new file mode 100644 index 0000000..b82ff16 --- /dev/null +++ b/docs/the-myth-of-the-users-journey.org @@ -0,0 +1,319 @@ +#+title: The myth of the "user's journey" +#+AUTHOR: Viktor Gridnevsky, Aleksandr Petrosyan and friends +#+DATE: 16.02.2025 +#+LANGUAGE: en_GB + +* The myth of the "user's journey" +:PROPERTIES: +:CUSTOM_ID: the-myth-of-the-users-journey +:END: +Sometimes I do frontend development. As a learner I have a strange +perspective: designers imposing their ideas on users. I believe it +likely harms both producers and consumers in the long run, which may not +be obvious from the get go and is worthy of a discussion. + +** Controlling the narrative +:PROPERTIES: +:CUSTOM_ID: controlling-the-narrative +:END: +Designers often believe they must "map the user's journey"[fn:1], +tracking every step from "arrival to purchase". They approach it like a +sales pitch, defending it through an appeal to popularity. The vast +majority of the users are annoyed and disgusted with ads[fn:2], but +accept it as a norm[fn:3]. We use adblockers pretty +actively [fn:4] [fn:5] [fn:6] [fn:7], although I rarely hear about +people objecting to the very idea of the ad industry continuing to +exist. We even seem to have silently accepted the premise of ads being +used to track us[fn:8]. The myth of the perfect user journey typically +assumes users are clueless and need to be shown what to do. It falls +apart when real people interact with real designs. If you think that +way, your program will likely repel people. Many will leave, disgusted. + +I think we'll live in a better world if more of us blocked ads. The +intentional use of "pattern interrupts" on low-quality ads[fn:9] reduces +our focus while the surveillance capitalism is built around monetizing +our data and turning it into a self-reinforcing cycle. It's almost a +must these days, yet we are fed propaganda about how blocking ads is +wrong[fn:10][fn:11]. It resembles a popular misdirection that blames +regular people[fn:12] for CO₂ emissions instead of big companies and +billionaires with their expensive cars and private jets. + +I recently attempted to apply for a job, and the process was anything but simple. +I won’t lie, The frustrating user experience adds insult to the injury of an +already exhausting struggle for employment. +And yet, that’s just how things are in 2025. At least for me, and I apply often. +Business as usual. +Not sure what the experience is like? Let me walk you through it. +At a certain point, the registration to apply opened for a limited time. +A timer counted down to zero, then started counting up. No application form appeared. +I sent them a video of the issue and my resume. +Around 12:30 AM, they fixed the bug without me getting any reply. +I opened the form. I uploaded my resume. +The system tried to extract my photo but pulled the header's background picture +with a plant texture instead. Now, in their system, I'm not me. +I'm a bush, fern, to be more specific. +I tried uploading a real photo. +It erased my name, surname, and other details. I was either a fern with work experience +or nothing at all. So, I tried hard to fix it and I failed. +The problems I won't dwell on, continued. Finally, I submitted the form. +You can call me Mr. Fern now. + +Here's another example. Imagine your pet dog is sick, you need to +quickly take them to their vet. Lots of vets around but the competent +one lives far away. Literally hours of walking, with a dog that has +internal bleeding. Surely, in the modern day you can order a taxi, and +simply tick a box saying "I am trasporting a pet". Happy accident, sadly +you can't specify that it's a medium-sized breed, and so the taxi driver +flips you off and stays in the vicinity to make you have to pay for the +cancellation. Is the taxi driver to blame? Maybe. But I think the +context is what drove the problem; there isn't enough expressive power +in /what kind of pet/ is being trasported. + +The taxi app could fix this. It could add a simple option, letting you +mark if you need more space than a regular car but much less than a +delivery truck. It wouldn't just be for dogs, it could be for anything. +You'd be happier. But instead, you're have to cater to how a shitty app +works. The shitty app reduces the options down to a single boolean. The +problem isn't the answer, the problem is the kind of question that the +app asks of you. + +Not all cars are owned by taxi companies. People buy their own cars, big +or small, and use taxi apps to earn extra money. A simple text field for +comments could save both customers and drivers time and hassle on +reordering an appropriate taxi. One person might write, "I have a +shelf", another, "I'm with a dog", and some might not need to write +anything at all. I've heard people talk about simplifying apps and +cutting back on support, often pointing to Google as a successful +example. I wonder: "Is it worth it?". + +I think I am not alone in my assesment, even though my conclusions on +the design assumptions may differ. One of the popular tendencies I hear +about nowadays are the "everything apps", for instance WeChat in China. +The idea of seamlessly integrating multiple services, such as messaging, +social media, payments, shopping, and more, is certainly appealing to +me. + +The centralization of "everything apps" brings to mind the famous +aphorism often attributed to Sir Francis Bacon: "knowledge is +power"[fn:13]. People who possess relevant knowledge may be able to +exert control and influence others. In the context of "everything apps", +this knowledge encompasses /everything that defines you as a citizen/: +your documents, location, bank account details, and more. The ability to +exert large-scale control over these aspects is appealing both to +governments and large corporations. For you, it is a single point of +failure: a key you cannot afford to lose, a single door to your +business, a tool that could ultimately dictate your choices, leaving you +with no alternatives. In that context, decentralised, open protocols +have a potential to be better than the idea of "everything apps". While +not eliminating personal risks I just pointed with "centralised +systems", the decentralized designs aren't inherently built to favour +one side, gaining control simply because it can. + +Last week, a driver drove far past my location. I had to run half a +kilometre to catch up. A photo of my location could have saved us both +time. Neither did I blame this gentleman back then, nor do I blame him +now, but I do think a feature with a location photo would help. I've +seen this as a requirement in scooter rental apps, so why not add it to +taxi apps? + +Lastly, I'd like the option to freeze a small amount of money on my card +when I book a ride. This way, I wouldn't have to wait to confirm +payment. If the app freezes a bit extra, it would work well, and the +taxi company could still track the exact amount for their records. + +The way a user understands an idea might not match how the development +team sees it. This difference adds complexity. Instead of assuming the +idea of "an abstract, clueless user", we should talk with people to +understand their needs, group them by understanding their needs, and +make it inclusive by designing programs for everyone. + +** Halo effect +:PROPERTIES: +:CUSTOM_ID: halo-effect +:END: +Designers often pick bad solutions because of the +"[[https://www.britannica.com/science/halo-effect][halo effect]]". They +want to look good, seem effective. If something is even slightly +associated with selling well, they push it, even on the sites that don't +sell things. In the end, the users suffer for them to even attempt to +look good. The users have to deal with a bad tool, as if the "a tool +exists for the user" rule was inverted. While some publications suggest +that aggressive marketing can increase interest in a product, and while +the publishers may have a certain level of renown, scientific or +otherwise, it raises the question: are these claims based on genuine +research and experience, or are they driven by the pursuit of short-term +profits from ads, especially given the existing systemic prioritization +of profit-maximizing interfaces? We should ask ourselves: could +businesses make more money by making their systems more open, instead of +sticking to designs that pretend to sell, but are painful to the users? + +Some designs aren't just bad, they're sneaky. Take buttons like *"kick"* +and *"ban"*. Putting them where they're easy to click isn't an accident, +while the useful features are buried is something that is called a "dark +pattern". It pushes people to act fast, without thinking. Tools for +cutting people off are right there, front and centre. This isn't just +poor design. It's a *plan*. It stirs up drama and conflict to keep users +hooked. The fix isn't tweaking these choices. It's giving users control. +Let them *set up their own interface*. Even better, move to an *open +protocol*. That way, people can use open-source tools to interact how +they want. + +** Tabs versus spaces +:PROPERTIES: +:CUSTOM_ID: tabs-versus-spaces +:END: +As we grow older, vision and hearing fade. Accessibility becomes +essential, not optional. We shouldn't trap users in rigid designs. +Instead, we need simple protocols and APIs for everyday tasks: forms, +shopping, and more. + +The UX of code editing is discussed very often, but we don't hear about +the accessibility for the visually impaired that often. While reviewing +this article, Alexander added a great reference: the +"[[https://www.reddit.com/r/javascript/comments/c8drjo/nobody_talks_about_the_real_reason_to_use_tabs/][Nobody +talks about the real reason to use Tabs over Spaces]]" article. Its +author, [[https://www.reddit.com/user/ChaseMoskal/][Chase Moskal]], +recently worked at a company that used tabs for indentation. Stressing +the need for consistency in coding environments, he started pushing for +spaces instead. As he did it, two coworkers approached him, both are +visually impaired. One uses a tab width of 1 because they need a very +large font to read code. The other uses a tab width of 8 on a wide +monitor to fit their needs. He wrote that given their vision challenges, +it's impressive they can code at all. These choices aren't about being +picky, they're about not doing the extra work each time due to your +existing health condition. + +Businesses must balance their needs with user control. This might mean +moving past traditional browsers and mobile apps, which only help a few. +Most apps are inflexible. They favor fixed designs over adaptability. We +could connect the protocols I have mentioned above to open-source +software. This would create dynamic interfaces tailored to individual +needs, whether it's a clean form or a text option for the visually +impaired. RSS and Gemini prove this: cutting the ad-driven clutter makes +technology more accessible. + +Businesses win when they let customers control how they interact[fn:14]. +Users win, as having more control makes things both safer and more +convenient for them. + +Once, I found a useful program written in [[https://go.dev/][Go]] +language. It showed how breaking away from a company's standard design +can make things faster and easier. It let you order Domino[fn:15]'s +pizza from the command line. It made me think: I don't want to see some +shop's design. Moreover, I don't want to scroll through their news or +product recommendations. What I want is pizza. I can, in a few minutes, +create a physical button in your kitchen: one press, and it orders your +usual pizza. A desktop shortcut that does the same, if you prefer that. + +*** Ownership +:PROPERTIES: +:CUSTOM_ID: ownership +:END: +I like thinking of my own tools, because understanding them makes my +life smoother. These ideas cut out the extra steps and make ordering +quick and simple. This helps businesses too. If my tool works exactly +how I want, I'll order more often. Companies should make their services +fit how customers want to use them, not force a single way[fn:16]. So +here's to DIY pizza buttons. One for each topping. And a delivery timer. + +The APIs online shops make should also focus on support. Think about +having support contacts built into an API. Right now, most support +systems feel disconnected. They ask for extra information, require +authentication, and create headaches. A support API would be better. I +could use it from any app, on any device, and it would sync seamlessly. +I don't want to be stuck with clunky support interfaces, but that's +where we are today. + +After reading this article, my friend asked me to expand on a few +points. He wanted to talk about a problem tied to aging: older people +often don't want "design innovation". They don't care for flashy, new +buttons. They want things to stay predictable. If a design changes too +much, they'll likely ask younger people to help them understand it. +Updating designs also adds costs, like translating text. Sometimes, new +designs are launched without being adapted for different languages or +regions. This makes the user experience even harder for them. Worse yet, +I see "accessibility systems" integrated into shop websites, and let me +tell you, I want none of that nonsense. Native accessibility is much +better than having to adapt to many "accessibility designs", and I can +say it as my vision is getting worse. + +Discussing this article, I was recommended Dieter Ram's "Ten Principles +for Good Design", or "/The Design of Everyday Things/" by Don Norman, +which I am grateful for. This article is only a starting point for a +conversation about moving toward better, more sustainable designs. It's +far from a finished product, and I see this as part of my own learning +journey. Every piece of evidence, whether from literature or +discussions, adds to this evolving exploration. + +In conclusion, forcing the users into rigid, profit-driven designs only +drives us away. By focusing on user control, accessibility, and +flexibility, businesses can stay in touch with their userbase, build +loyalty and earn trust. A design that respects the user's needs isn't +just morally right, it's good business. After all, happy users are +returning users. + +[fn:1] As a *neutral* reference for the sake of this article, the + "[[https://www.youtube.com/watch?v=wIuVvCuiJhU][world's shortest + UI/UX design course]]" by Juxtopposed would suffice. My intention + isn't to criticise the Juxtopposed, who simply shows the idea of + "mapping". + +[fn:2] [[https://www.statista.com/forecasts/1452640/share-of-people-getting-annoyed-by-online-ads-in-selected-countries-worldwide][Share + of people getting annoyed by online ads]] in 53 countries & + territories worldwide, as of January 2025 + +[fn:3] [[https://www.statista.com/forecasts/997054/attitudes-towards-online-advertising-in-the-us][Attitudes + towards online advertising in the U.S.]] as of December 2024. + Personally, though, I think "I am often annoyed by advertising on + the Internet" as the "highest category" limits the picture, as + there are people taking an active stance against the ads. + +[fn:4] [[https://blockthrough.com/blog/2022-pagefair-adblock-report/][2022 + PageFair Adblock Report]] shows that at least 290M people monthly + use ad blockers globally + +[fn:5] [[https://today.yougov.com/politics/articles/16318-why-people-use-ad-blockers][Annoying + ads]]: Just one of the many reasons why people use ad blockers + +[fn:6] [[https://www.gwi.com/hubfs/Downloads/Global_Ad-Blocking_Behavior.pdf][Global + Ad-Blocking Behavior]] (2019) + +[fn:7] [[https://www.forbes.com/sites/tjmccue/2019/03/19/47-percent-of-consumers-are-blocking-ads/][47 + Percent Of Consumers Are Blocking Ads]] + +[fn:8] [[https://timsh.org/tracking-myself-down-through-in-app-ads/][Everyone + knows your location]]: tracking myself down through in-app ads + +[fn:9] Reddit: "Can someone please explain + [[https://www.reddit.com/r/advertising/comments/joyg4e/comment/gbc2tx9/][why + there are so many poorly designed and frequent ads]] on + websites?" --- look no further than James Steadman (jcsteadman)'s + reply + +[fn:10] For an example calling blocking ads "piracy", look no further + than "[[https://www.youtube.com/watch?v=a-PH2GUy_zM][Is Adblock + Piracy?]]" by Linus Sebastian + +[fn:11] Louis Rossmann provides a number of arguments against "ads as + piracy"[^Linus_ads] in + "[[https://www.youtube.com/watch?v=6jUxOnoWsFU][Linus says + adblock is piracy: is he right?]]" + +[fn:12] There's a relevant conversation of how the ecological + responsibilities are represented in + "[[https://youtu.be/uCuy1DaQzWI?t=5498][Kurzgesagt and the art + of climate greenwashing]]" and + "[[https://www.youtube.com/watch?v=DGfBV4I8DQI][Kurzgesagt: + billionaire propaganda, trusting science, and effective + altruism]]" + +[fn:13] Or, originally, "scientia potentia est" + +[fn:14] I was told a story about Gaudi allowing the workers to decorate + the wall and winning from it, but I am yet to find some link to + the story. Please contact me if you have one. + +[fn:15] Who I really am grateful to for presenting such an API + +[fn:16] My friend still uses Windows XP in 2025, and I quote here "out + of sheer disgust towards the newer designs". \ No newline at end of file diff --git a/docs/xkcd_dependency.js b/docs/xkcd_dependency.js new file mode 100644 index 0000000..751c885 --- /dev/null +++ b/docs/xkcd_dependency.js @@ -0,0 +1,83 @@ +function SVG2MatterCoords(x, y, width, height, scale, hShift, vShift) { + let matterX = (x + width / 2) * scale + hShift; + let matterY = (y + height / 2) * scale + vShift; + let matterWidth = width * scale; + let matterHeight = height * scale; + return { + x: matterX, + y: matterY, + width: matterWidth, + height: matterHeight + }; +} + +function calculateMass(width, height) { + return width * height * 0.0003; +} + +function loadRectanglesFromJSON(url, world, scale = 15, vShift = 0, hShift = 0) { + fetch(url) + .then(response => response.json()) + .then(data => { + const bodies = data.map(item => { + const converted = SVG2MatterCoords(item.x, item.y, item.width, item.height, scale, + hShift, vShift); + const weight = calculateMass(converted.width, converted.height); + return Matter.Bodies.rectangle(converted.x, converted.y, converted.width, converted + .height, { + mass: weight, + render: { + fillStyle: '#888' + }, + }); + }); + Matter.World.add(world, bodies); + }) + .catch(error => console.error('Error loading JSON:', error)); +} + +function addDependencyMeme() { + const engine = Matter.Engine.create(); + const world = engine.world; + const render = Matter.Render.create({ + element: document.querySelector('#interactive-block'), + engine: engine, + options: { + width: 500, + height: 500, + wireframes: false, + background: 'transparent', + } + }); + document.querySelector('#interactive-block').insertAdjacentHTML( + 'beforeend', + '

Inspired by XKCD 2347: Dependency.

' + ); + const ground = Matter.Bodies.rectangle(400, 496, 900, 20, { + isStatic: true, + render: { + fillStyle: '#666' + } + }); + Matter.World.add(world, ground); + const mouse = Matter.Mouse.create(render.canvas); + const mouseConstraint = Matter.MouseConstraint.create(engine, { + mouse: mouse, + constraint: { + stiffness: 0.2, + render: { + visible: false + } + } + }); + Matter.World.add(world, mouseConstraint); + render.mouse = mouse; + loadRectanglesFromJSON('xkcd_dependency.json', world, 4, -110, -185); + Matter.Runner.run(engine); + Matter.Render.run(render); +} + +const script = document.createElement("script"); +script.src = "https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"; +script.onload = addDependencyMeme; +document.head.appendChild(script); \ No newline at end of file diff --git a/docs/xkcd_dependency.json b/docs/xkcd_dependency.json new file mode 100644 index 0000000..553a020 --- /dev/null +++ b/docs/xkcd_dependency.json @@ -0,0 +1,368 @@ +[ + { + "x": 104.31146, + "y": 44.502277, + "width": 1.8086538, + "height": 3.9504807 + }, + { + "x": 106.92924, + "y": 45.501797, + "width": 1.0947115, + "height": 2.9509614 + }, + { + "x": 109.02348, + "y": 45.787373, + "width": 1.2375001, + "height": 2.6653848 + }, + { + "x": 104.12107, + "y": 48.595665, + "width": 6.6158652, + "height": 2.5701921 + }, + { + "x": 102.02684, + "y": 51.328922, + "width": 4.4264421, + "height": 3.0461538 + }, + { + "x": 107.73838, + "y": 51.328922, + "width": 4.4740386, + "height": 3.0461538 + }, + { + "x": 102.5504, + "y": 54.522926, + "width": 8.4245186, + "height": 10.471154 + }, + { + "x": 113.73547, + "y": 54.578907, + "width": 1.7134267, + "height": 3.9980769 + }, + { + "x": 112.54559, + "y": 58.74284, + "width": 3.3792584, + "height": 6.235096 + }, + { + "x": 97.457611, + "y": 55.656281, + "width": 3.7600961, + "height": 2.4274037 + }, + { + "x": 98.742706, + "y": 58.236252, + "width": 1.6182692, + "height": 3.6649039 + }, + { + "x": 97.505211, + "y": 62.033016, + "width": 3.0461538, + "height": 2.8557694 + }, + { + "x": 98.076363, + "y": 65.136391, + "width": 17.277403, + "height": 3.3793271 + }, + { + "x": 110.40376, + "y": 68.650963, + "width": 2.9033654, + "height": 2.984617 + }, + { + "x": 99.742226, + "y": 68.652596, + "width": 4.9975958, + "height": 4.8072114 + }, + { + "x": 101.50329, + "y": 73.58461, + "width": 2.1418269, + "height": 6.9942431 + }, + { + "x": 104.21627, + "y": 77.187981, + "width": 2.7130375, + "height": 3.400425 + }, + { + "x": 109.26146, + "y": 71.762016, + "width": 4.4740386, + "height": 4.062501 + }, + { + "x": 108.49992, + "y": 75.955284, + "width": 6.949038, + "height": 19.553852 + }, + { + "x": 116.35329, + "y": 80.494278, + "width": 1.1899039, + "height": 2.5225961 + }, + { + "x": 118.87589, + "y": 81.17128, + "width": 1.6182702, + "height": 1.8562466 + }, + { + "x": 115.87733, + "y": 83.159126, + "width": 4.8548074, + "height": 2.6653848 + }, + { + "x": 117.30521, + "y": 85.977501, + "width": 1.9514422, + "height": 3.9504807 + }, + { + "x": 116.78165, + "y": 90.064911, + "width": 3.8552885, + "height": 5.4735575 + }, + { + "x": 100.14813, + "y": 80.70047, + "width": 6.1253123, + "height": 14.808448 + }, + { + "x": 95.974846, + "y": 82.583282, + "width": 1.3462225, + "height": 2.0866449 + }, + { + "x": 95.436356, + "y": 84.808411, + "width": 2.8943787, + "height": 1.8847115 + }, + { + "x": 96.244087, + "y": 86.848663, + "width": 1.6154671, + "height": 5.5531678 + }, + { + "x": 94.56131, + "y": 90.776512, + "width": 1.4808729, + "height": 1.6154671 + }, + { + "x": 94.897865, + "y": 92.547226, + "width": 4.1059785, + "height": 2.9616897 + }, + { + "x": 94.292068, + "y": 95.676216, + "width": 25.64554, + "height": 9.8947353 + }, + { + "x": 94.494003, + "y": 105.76953, + "width": 23.828138, + "height": 8.8538046 + }, + { + "x": 71.473595, + "y": 114.79064, + "width": 45.973495, + "height": 13.462225 + }, + { + "x": 74.031418, + "y": 128.43987, + "width": 41.329029, + "height": 3.076597 + }, + { + "x": 110.37943, + "y": 131.61024, + "width": 2.4905117, + "height": 7.5796776 + }, + { + "x": 75.51226, + "y": 131.68378, + "width": 12.048691, + "height": 4.1699071 + }, + { + "x": 73.089066, + "y": 136.0244, + "width": 15.54887, + "height": 3.0963118 + }, + { + "x": 68.64653, + "y": 139.28802, + "width": 51.29108, + "height": 5.5834413 + }, + { + "x": 64.877106, + "y": 145.03282, + "width": 62.147423, + "height": 5.0204539 + }, + { + "x": 72.564827, + "y": 55.314281, + "width": 1.5468749, + "height": 3.0937498 + }, + { + "x": 72.493431, + "y": 58.593174, + "width": 1.6182692, + "height": 7.9009614 + }, + { + "x": 74.873238, + "y": 60.721836, + "width": 2.6177886, + "height": 2.4750001 + }, + { + "x": 74.70665, + "y": 63.328949, + "width": 2.8795671, + "height": 3.1651437 + }, + { + "x": 71.113144, + "y": 66.617981, + "width": 5.4973559, + "height": 1.5706731 + }, + { + "x": 72.779007, + "y": 68.315002, + "width": 1.9990385, + "height": 3.9266827 + }, + { + "x": 75.872757, + "y": 69.12413, + "width": 1.2612981, + "height": 3.117548 + }, + { + "x": 69.899437, + "y": 69.814278, + "width": 2.3084135, + "height": 2.4274037 + }, + { + "x": 70.87516, + "y": 72.378723, + "width": 7.7343745, + "height": 2.0942309 + }, + { + "x": 79.775642, + "y": 71.423569, + "width": 1.5468749, + "height": 4.4502406 + }, + { + "x": 78.347755, + "y": 76.016121, + "width": 3.3079326, + "height": 3.9266827 + }, + { + "x": 71.803284, + "y": 74.709892, + "width": 4.3788462, + "height": 5.2593751 + }, + { + "x": 70.3992, + "y": 80.124756, + "width": 20.513943, + "height": 4.2783751 + }, + { + "x": 69.050392, + "y": 84.535263, + "width": 24.030071, + "height": 30.115955 + }, + { + "x": 83.387665, + "y": 74.479057, + "width": 7.3369126, + "height": 5.4522014 + }, + { + "x": 83.791527, + "y": 62.609337, + "width": 5.9233794, + "height": 11.712136 + }, + { + "x": 86.010735, + "y": 49.51828, + "width": 2.1180289, + "height": 2.5463943 + }, + { + "x": 88.771317, + "y": 49.864666, + "width": 1.8086538, + "height": 2.1894231 + }, + { + "x": 86.08213, + "y": 52.212269, + "width": 4.1408653, + "height": 3.0223556 + }, + { + "x": 87.367226, + "y": 55.463642, + "width": 1.9990385, + "height": 6.9966345 + }, + { + "x": 83.083572, + "y": 56.408279, + "width": 3.8314903, + "height": 1.7372595 + }, + { + "x": 84.654243, + "y": 58.28516, + "width": 1.7610577, + "height": 4.1884618 + } +] \ No newline at end of file