Making Memes
Fnord.
Making memes
I'm ahead of schedule on workshop prep, which means I have time to think about things besides pedagogy and formal methods. And I've been thinking of a kind of article I commonly write:
- Here's some examples of something.
- I am going to give that thing a name.
- Now that we have a name, let's discuss it as its own topic.
Examples: edge case poisoning, mimicry, cleverness vs insight, constructive and predicative data.
Doing this creates a (minor) branch of human knowledge, in the form of a topic, that then has a distinct existence independent of the original examples. It's more transmissible than the information, but also makes the contained information more transmissible by acting as a handle to it. It's easier to find information on "patterns" because we have a topic of patterns. Topics can also be expanded, like how there's now "testing patterns" and "performance patterns"; discussed independently of the information, like with "patterns are just missing language features" discourse; and related to other topics, like "'patterns are missing language features' means 'patterns are an example of mimicry.'"
In other words, it's a meme! The original idea of memes as units of cultural transmission, I mean. I tried learning more about old-school memetics but my cursory research suggests it became a navel-gazey sort of uberfield that got too focused on how Memes Are Important without actually doing much with it.
So let's try to pretend that whole field never happened and see what we can do with creating a new topic.
Let's make a meme!
(I thought up this specific concept while on a walk earlier today. I have no idea how consistent the actual idea is, I'm just using it as an example of memetics.)
Let's start with the example. Oftentimes I write small scripts. Following YAGNI, I don't try to make the script too general, just the simplest thing that solves my task at hand. Sometimes I want run these scripts with different inputs. This doesn't happen often, so I don't implement it until I need it. When I do need it, though, I know exactly how I add that feature: parameterize the script and add CLI flags.
So I have a program, and a possible new requirement for the program, and I know exactly how I'll change the program to handle that requirement. I want to bundle "changed requirement + known change to program" into a concept. I'll call it Understood Potential Changes, or UPCs, because coming up with elegant names is hard and this is just a toy anyway.
As soon as we create the concept, we also create the associated category. Some things count as UPCs and some things don't. "If the program gets to slow, here's the main bottleneck we'll change" is a UPC. "If marketing asks for X, we'll figure it out then" is not a UPC. Finding things that count makes the definition clearer. And it makes the topic useful: if there's knowledge associated with the topic, we can apply it to things inside the category.
Speaking of associated knowledge, there's actually two things we can study. We can look at properties of UPCs, and we can look at properties of the concept of UPCs. "Properties of UPCs" is what makes the concept itself (possibly) worth knowing, so let's start with that.
Properties of UPCs
First of all, UPCs are a form of domain knowledge, where the knowledge is "the program". It's not actually in the program. It's in your head, or a design document somewhere. You find them from either prior experience or by spending time thinking about stuff.
Having UPCs lets you move quickly and keep the program simple while minimizing risk. If you don't have a UPC, you have to figure out program changes after you get the requirement, which can potentially throw you off balance. Also, you can evaluate how program modifications affect the UPCs. Maybe there are two ways you can do X, but one closes off more UPCs than the other, so reduces your flexibility. Finally, knowing UPCs can make you more confident about certain changes: "we can safely build this feature because we know exactly what to do if requirement change X happens."
UPCs have a likelihood and difficulty. Likelihood is how likely it you'll have the changed requirements. Difficulty is how hard the corresponding change will be. A requirement can have multiple possible program changes with different difficulties. And they can have different unintended consequences: just because you know what the changes looks like doesn't mean you know how the final implementation will affect the overall program.
There are also properties in how UPCs relate to each other. Two UPCs are incompatible if doing one closes off the other. Incompatibilities for the same requirement aren't a problem, but incompatibilities across different requirements can be extremely painful. Two UPCs are linked if they are different requirements but share the same change. Like how replacing a single value with an event source array addresses both "we need to undo changes" and "we need to know what entity caused a change." If a lot of UPCs are linked to the same change, it's probably a good change?
Properties of "UPCs"
The "operations" on a concept are more broad, and we can apply them to a lot of different concepts, though they'll give different information.
First, UPCs is a category, and all categories are fuzzy. There is a collection of things that aren't clearly in or out of the set.1 A Reuben is definitely a sandwich, a salad is definitely not a sandwich, but is a hotdog a sandwich? And are operational changes UPCs? "If we have too many users, we'll start using a load balancer." That's a way to address a requirement change but isn't necessarily a change to the code. Or what about known changes with lots of unknown details? "If we need to do X we'll first rewrite the script from Python to Go." Finding fuzzy items tells us the limits of the definition, and suggests variations that definitely include/exclude the topic.
Second, we can specialize categories: look for well-defined subsets, like "UPCs related to performance changes" or "UPCs where implementing the solution requires specific expertise in technology X." Subsets are useful because they have more properties, like there's more you can say about the set of "POSIX-compliant programs" than the set of "programs". We can also generalize and look for a well-defined superset, like "reactions to requirements", "mental counterfactuals", or "binary relationships". Generalization is useful because there are a lot of potential generalizations, which opens up other potential operations.
Third, we can look for relationships to other ideas. Some I see:
- UPCs are a way to minimize the downsides of YAGNI.
- Future-Proofing is when you modify a program to provide UPCs, not to address an immediate feature. Generally it's considered a bad idea.
- Brian Hicks wrote advice you might as well take, about future-proofing that is generally a good idea. If we think of them in terms of UPCs, "good future-proofing" is when you have a likely UPC that's exceptionally easy to close off.
Finally, we can look for variations. Can we adapt the idea to different domains? Is there some other aspect of the relationship that, when included, adds more insight? Or maybe we don't vary UPCs itself, but use it as a springboard to develop an entire new concept.
The meme
So I said that UPCs is a meme. All concepts are— they can spread from person to person. And the memetics material I've read all gets fixated on spread as "contagion" or "virality" or "evolution", which all make it sound sinister. You get infected with a meme. This is stupid. It's more interested to think of it in terms of rational processes. People hear the concept and think "hmmm yeah this seems useful" and then they consciously share it with other people because it's a useful concept. Maybe it looks like virality at the macro level but it looks totally different at the micro level.
Anyway, looking at UPCs as a meme means trying to figure out how people interact with it and why that happens. Do people think it's useful or not? Do people keep mostly to the idea as described, or do they play with variations? Do they actively look for UPCs and/or do they passively come up with them? Does it change how they develop code?
There's also memetic engineering, where you try to make the meme spread more easily. Once again the existing literature has this weird quasiconspiratorial vibe of "MARKETERS can CHANGE your BRAIN" that makes the whole idea sound inane to us normies. But memetic engineering is both doable and totally mundane.
For one, just look at your choice of examples! I motivated the idea with "adding a CLI to a script", but that might not be the best choice for communicating the idea. If I spend time finding better examples, it'll be easier for me to show the value of the idea (if any) to other people! Especially if I find examples in their niche.
Also I could adapt how I explain UPCs to my audience. Like it's one thing to communicate an idea with peers, and another thing to teach an idea to students. Different approaches, different examples, different reasons.
Another way you can engineer a meme: making the information easy to access. A lot of people don't do this! Like metamorphic testing is a really powerful testing technique, but until I wrote that article all the available information was behind paywalls.
None of these engineering change the idea of UPC, just how it's represented. You absolutely can make a meme more spreadable, in a totally benign way. And also none of these guarantees how people will react to a meme. All of these are possible outcomes:
- Nobody ever thinks about UPCs again.
- A few people like it and use it a few times.
- Everybody thinks its stupid and I'm forever known as the guy who tried to take memetics seriously.
- Someone reads it, gets inspired, comes up with a different idea, and that takes off.
- UPCs somehow take over the world and now there's a cottage industry of thought leaders selling $50,000 courses and I turn into a crazy person.
(Not all of these are equally likely, but they're all possible!)
The cybernetics trap
I like this kind of analysis a lot but it looks dangerously close to being an "uberfield", like cybernetics or systems thinking. Some people in those fields got so caught up in the dream of the paradigm shift that they forgot to make the field useful. This kind of transdisciplinary thinking must always be subservient to ordinary practice; it must provide us with technology.
The technology, in this case, is the operations on concepts. It's not a groundbreaking discovery, just a few useful ways to take an idea and systematically explore it.
But I still think it's cool technology, and one I hope more people find useful. I think the field of software engineering will benefit if we take the time to create more concepts and relate them to each other. And it's fun!
Anyway, to close out ~2000 words on meme-rehabilitation, have some Rick Astley.
Man I love Rick Astley
-
"Fuzziness" is also a concept, which means we can apply the same analysis. In particular, there's different kinds of "fuzzy": "everybody is uncertain if it's X or not" is a different from "half the people are sure it's X and the other half are sure it isn't." ↩
If you're reading this on the web, you can subscribe here. Updates are once a week. My main website is here.
My new book, Logic for Programmers, is now in early access! Get it here.