Jekyll2021-07-16T16:02:54-07:00http://chrisstead.net/feed.xmlChris Stead – Software, Centered on HumansThe ramblings of a software engineer working with Javascript driven to the brink of madness and reporting back from the edge.
Chris SteadYog’s Law: Power, Responsibility, and Accountability2021-07-16T01:00:00-07:002021-07-16T01:00:00-07:00http://chrisstead.net/power-dynamics/yogs-law/workplace-safety/2021/07/16/yogs-law-power-responsibility-and-accountability<p>Though it’s a years-old news story, Volkswagen produced a diesel-powered car which was designed to pass emissions checks although, under normal operation, the vehicle produced emissions which would not have met an acceptable threshold. The company threw a newly-minted engineering middle manager under the bus for cars being shipped with this <a href="https://en.wikipedia.org/wiki/Volkswagen_emissions_scandal">emissions-check-defeating feature</a>. This abuse of power placed responsibility for a clear flouting of emissions laws directly on someone who was not in a position to drive design or business decisions. The emissions system in cars typically goes through a number of hands, and checks before mass production. This means coordination would have been necessary between many teams to produce a vehicle which would violate US law.</p>
<p>If we look at the chain of responsibility in software development, each time a project manager tells a software developer they are “accountable to complete all work by the end of the sprint” it is an assignment of responsibility. Accountability would involve communicating as work is being done, surfacing new risks, providing insight into the progress being made. Instead, the developer is being told, if they fail to foresee all risk, and surface it before beginning the work will be held responsible for “failing the sprint”.</p>
<p>In the cycle of promotion, a developer may be placed in a lead position. Once they are put in that position, they are informed “the management is looking for a throat to choke”. In other words, the lead is not responsible for guiding and aiding the team. Instead they are put in place as a responsibility fall-person, or a developer whip.</p>
<p>Ultimately, it is so common for responsibility to be pushed downward into the laps of the people doing the work, I find it difficult to point out teams I have seen in which responsibility is intentionally held by management.</p>
<h2 id="yogs-law">Yog’s Law</h2>
<blockquote>
<p>Money should flow toward the author – Yog’s Law</p>
</blockquote>
<p>What Yog’s law is referring to is the need for authors to limit their outlay of money while looking for publication. Authors perform the creative work, they do the legwork to find publishers, and they submit their work. Once the work is submitted, the publishers need not ask for payment to review and publish the work. In fact, publishers will typically profit from publishing written works. Authors may not always get paid for their work, but the flow of money should not move from the author toward the publisher.</p>
<p>I don’t remember exactly when I first became aware of Yog’s Law, but I do know I was playing bass in a gigging band. When you look for gigs, you have to deal with venues and all of the foibles that come with. The good venues listen to a demo of some sort, check out the band, and then decide whether the band will be a good fit to play. It’s kind of an interview process, and it’s tough. The bad venues are “pay to play”. The venue requires the band to pay for tickets up-front which they must resell to get people out to the show.</p>
<p>Yog’s Law talks about the flow of money toward authors, but it could really be said about any creative endeavor. I used Yog’s Law as an argument for why my band must not play at pay-to-play venues, and we didn’t. We played bars, county fairs, house parties, and all kinds of other shows. We often played for free, especially in the beginning. We never went out of pocket to play.</p>
<p>I would go so far as to say, Yog’s Law, at its core, is about power. Money is representative of power The flow of money is indicative of the direction power flows in a creator/publisher relationship. Creators perform the act of making a thing, but publishers hold the power to disseminate the work. In writing, publishers distribute the work, and hold the purse strings. In the case of my old band, the venue acted as the publisher. In an employment environment, the worker is representative of the author. The business, and those who guide it, act as the publisher.</p>
<h2 id="the-power-lemma">The Power Lemma</h2>
<blockquote>
<p>Power should flow toward the worker.</p>
</blockquote>
<p>If Yog’s Law is about power, then the flow of money is representative of the flow of power. I believe the relationship between money and power is pretty clear in the wild. Though power may not always come with money, typically, with money comes power. This means, someone who holds power over another person likely also controls the flow of money to that person.</p>
<p>If we scratch the surface just a bit, we can see how the publisher holds power by controlling the flow of money. Let’s assume, for a moment, that a publisher were to violate Yog’s Law. Money would flow from the author, to the publisher. Since a publisher controls the flow of money, and with it the power in the relationship, this reversal of monetary flow would be an abuse of power.</p>
<p>In the author/publisher relationship, when the flow of money is reversed, it becomes a relationship where the publisher requires money from the author. There are, in fact, publishers who require authors to pay review, editing, or even publication fees. Publishers who do this kind of thing are referred to as “predatory publishers”. In a broader sense, the reversal of Yog’s Law is an abuse of power, and produces predatory behavior.</p>
<p>This abuse of power extends to any creator/publisher relationship, including a work relationship. When a manager consolidates power, they disempower the people they manage. This disempowerment is an abuse of the power the manager holds. This same principle holds for the managers up the org chart.</p>
<p>The flow of power should be toward the worker. If we consider software development – an occupation with which I am intimately familiar – each developer must be empowered to make decisions about the tasks they perform. Much of the work done in (and out) an office requires a significant amount of latitude to be done well.</p>
<p>Workers need to feel they have the power to decide how to best accomplish the task at hand. When someone is disempowered, they feel micromanaged. A disempowered worker, for instance, begins to seek managerial approval for even the smallest tasks, which slows the process of producing work and hamstrings the delivery of value.</p>
<h3 id="the-shoulder-tap">The Shoulder Tap</h3>
<p>Due to the pandemic, people have been working remotely. As the number of vaccinated people rises, there is a discussion of what remote work looks like for companies going forward. People are urged to return to the office. Managers are expressing concern that there is a reduced level of collaboration with remote work, because people are not colocated.</p>
<p>There is a common refrain, “I can’t tap someone on the shoulder”.</p>
<p>As Chelsea Troy points out in her <a href="https://chelseatroy.com/2018/04/17/but-what-if-i-cannot-tap-my-remote-employee-on-the-shoulder/">article about the shoulder tap</a>, it is an exertion of power. In the article she points out, the manager is exerting power over the time and ability of the developer to do work. There are a number of reasons why the shoulder tap is disruptive, but I’d like to explore it from the flow of power perspective.</p>
<p>When a worker is working, they exercise their power to work on the task at hand, and produce some sort of result. The ownership of control over time and thought process is granted through empowerment to perform their work in the most effective way they can.</p>
<p>When a manager taps the worker on the shoulder, they have reclaimed the power granted to the person doing the work. Instead of power flowing toward the worker, the power has flowed back up to the manager.</p>
<p>When this shoulder-tap behavior happens regularly it is an exertion of power over the person doing the work. It is a means for the manager to seize control over the workday and steer it to their whim. We generally refer to this as micromanagement, but we can also consider it an abuse of power. Much like the predatory publishers who require authors to pay for publication, micromanagers perform predatory management, controlling the way workers approach their work and manage their time.</p>
<h2 id="the-responsibility-corollary-to-yogs-law">The Responsibility Corollary to Yog’s Law</h2>
<blockquote>
<p>Responsibility should flow toward management</p>
</blockquote>
<p>I’ve worked with managers who “empowered” workers by saying “you’re empowered to do whatever you think is best!” Of course, this is anything but empowerment. The problem is, there is no flow of power to the worker. Instead, there is a statement that the worker can simply do what they think may be best, but without any sense of support or guidance. In this kind of relationship, the worker becomes the responsible party, and must answer to people the manager is normally accountable to.This act of disempowerment through bestowing responsibility is what I would call <strong><em>responsibility shifting</em></strong>.</p>
<p>Empowering someone involves not only providing the latitude to do the work, but also, the guidance to identify an acceptable first approach, and the support to learn from the outcome. Empowerment requires energy and dedicated flow of power. When someone is trying something new, or different, there is a chance they will struggle and fail. I call this process of discovery, work, and reflection an <strong><em>experiment</em></strong>.</p>
<p>When failure happens, support is imperative, and it must come from someone with the power to shoulder responsibility for the experiment. The worker who ran the experiment was granted the power to do this, therefore they don’t have the power to carry the responsibility. The burden of responsibility must fall squarely on the shoulders of the person who empowered the worker.</p>
<p>As power flows toward the worker, responsibility flows toward management. This interchange of power and responsibility is core to the success of any one worker, team, or department. When power or responsibility flows in the wrong direction, it can lead to abuse, toxicity, and team failure.</p>
<h2 id="accountability">Accountability</h2>
<p>A common workplace discussion involves discussing accountability. People are said to be accountable to someone for the work to be done. Most often accountability is brought up by someone suggesting there was a promise made which has, or will, come due. Of course, if we are looking at a power/responsibility interchange, then this notion of accountability begins to fall apart.</p>
<p>So, what of accountability, then?</p>
<p>Accountability is often weaponized, and its use signals someone is shifting responsibility, and retaining power; E.g. “you are being held accountable for your promise to deliver.” In fact, the dictionary definition of accountability states it is a synonym to responsibility. I would, however, like to offer a different perspective.</p>
<p>I propose a law of accountability:</p>
<p><em>Accountability is the induced communication responsibility between two people who share a power/responsibility interchange relationship.</em></p>
<p>In other words, when people exchange power and responsibility, accountability is the responsibility for communication they share as partners in the work being done. The only way for responsibility and power to flow through an organization is through a foundation of communication. When power flows to a worker, and responsibility flows to the manager, the worker and manager need to have a clear communication channel to support their cause.</p>
<p>This means the person empowered to do the work is responsible for providing clear communication to the person empowering them to do the work. By turns, the person providing the power to do the work is responsible for providing clear, regular communication to the person doing the work. This is to ensure the worker has what they need and is kept abreast of any changes in priority or severity which occur.</p>
<p>This power/responsibility interchange and accountability cycle requires significant effort. All of this human interaction and relationship maintenance is necessary, to provide the best possible chance of success.</p>
<p>In other words, for work to be done effectively, everyone who holds a stake in the project must provide the appropriate elements to ensure success.</p>
<h3 id="failure-in-accountability">Failure in Accountability</h3>
<p>Let’s explore what happens when there is a failure in accountability. Since accountability provides a communication channel between the person empowering the worker, and the worker providing responsibility to the person empowering them, there are two places where accountability may fail.</p>
<p>Let’s first suppose the person empowered to do the work fails to uphold their accountability-driven communication. When a new risk emerges, and the person doing the work identifies it, but fails to communicate about it, it hobbles the person holding responsibility. This means the person doing the work has seized responsibility and has broken the power/responsibility interchange relationship expectation. Responsibility has flowed backward in the system and now resides with the person doing the work.</p>
<p>On the other hand, let’s suppose the person who empowered the worker fails to uphold their accountability communication. When a change in priority emerges and it is not communicated to the person doing the work, the work being done is inappropriate for expected outcomes, and the worker has been disempowered. The person empowering the worker has seized the power and has broken the power/responsibility interchange relationship expectation. Power has flowed backward in the system and now resides with the person originally empowering the worker.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Though Yog’s law was originally written to help new authors identify when they are being preyed upon, the implications in power and responsibility are far-reaching. In any effective team there must be a clear flow of power toward the people doing the work and a flow of responsibility toward the folks managing the people doing the work.</p>
<p>Accountability is induced by this power/responsibility interchange, and it drives the sustained health of the relationship. When the empowered people, and the responsible people are accountable to each other, work can be done more effectively, and value will be generated more readily.</p>Chris SteadThough it’s a years-old news story, Volkswagen produced a diesel-powered car which was designed to pass emissions checks although, under normal operation, the vehicle produced emissions which would not have met an acceptable threshold. The company threw a newly-minted engineering middle manager under the bus for cars being shipped with this emissions-check-defeating feature. This abuse of power placed responsibility for a clear flouting of emissions laws directly on someone who was not in a position to drive design or business decisions. The emissions system in cars typically goes through a number of hands, and checks before mass production. This means coordination would have been necessary between many teams to produce a vehicle which would violate US law.The Six Aspects of Software Development2021-06-29T01:00:00-07:002021-06-29T01:00:00-07:00http://chrisstead.net/software-development/human-centered-code/sociocognitive-software-development/2021/06/29/six-aspects-of-software-development<p>There is a sense of click-bait, and one of the most common forms is n-best lists. These are the 10 best basket weaving solutions on the market. Here are the 5 best practices of highly successful cat herders. Vampires HATE these 3 things do them to stay safe in your parking garage. They are right there. You almost want to click them to read more, right?</p>
<p>In the software development social sphere, the most pervasive n-best lists are things like “the 5 best skills to have as a software developer”, or “the 3 most important things you’ll do for your software development career”. Every time I see these lists, I can’t help but ask “are these really the most important things?”</p>
<p>Frankly most of the time, these people are putting a list together of the things which saved their butt today, or this week. To that end, I can’t blame them. On the other hand, claiming these things are the best ever seems a little disingenuous.</p>
<p>Over the past year or so, I have been diving into a lot of social science information. I did a six-month crash course on foundational linguistics topics. I’ve been reading about cognitive science. Lately, I’ve been reading about cognitive load theory. What I’ve come to believe is, the reason people don’t know where to put the new great thing they learned is, they don’t exactly know what way it helped them.<!--more--></p>
<p>People write software. Software is created for people. Software is really about people creating solutions for people. Of course, what this means is, every aspect of software is influenced heavily by the people who created it. Mel Conway recognized this in the 1960s, so this is not particularly new.</p>
<p>There is a pattern which gave me a clarity of thought regarding software development and how we can actually best use our energy to become better software developers. I can identify 6 distinct aspects of software development as a whole, and it’s really all about people. These aspects are:</p>
<ul>
<li>Understanding</li>
<li>Communicating</li>
<li>Teaching</li>
<li>Learning</li>
<li>Reading</li>
<li>Writing</li>
</ul>
<p>No software developer ever does exactly one of these things. Instead they are parts of a systemic whole which defines the way people go about software development day to day. Each of these system constituents represents an entire model of how we operate within that space. I won’t attempt to cover it all today. Instead, I’d like to propose how each of these aspects of the software development sociotechnical model impacts our daily work.</p>
<h2 id="six-aspects-of-software-development">Six Aspects of Software Development</h2>
<h3 id="writing">Writing</h3>
<p>When people think of software development, writing is the thing they think of most readily. In fact, what they really think of is just one very narrow aspect of writing software: writing instructions which tell the computer what it is supposed to do.</p>
<p>This naive understanding of software is what leads people, frequently, to the idea that everyone must “learn to code”. Of course, learning to simply write code is much like teaching someone the alphabet, handing them a book on grammar and a dictionary, and saying “get to work, you have a report to write”.</p>
<p>Writing software is an interactive process where the developer, or developers, consider a problem, and devise a solution. They validate the solution as they work by either testing inputs and outputs by hand, or writing automated tests which provide just-in-time feedback.</p>
<p>We can continue to expand our understanding of writing to include the automated tests. Skilled test authors capture a significant amount of information in their test suites. The entire generated set of source documents – tests and production code – are a written body of work which can, and will, be read by other developers who extend and support the software created by you.</p>
<h3 id="reading">Reading</h3>
<p>In its simplest form, reading source code is the process of looking at, and unraveling logical structures in a source document, then performing some rudimentary execution in your head to understand what happens when that code is run. This is, in my opinion, ill-advised. Computers can tell you what the code outputs when you provide an input.</p>
<p>With the development of automated refactoring tools, reading has become a much more active behavior. When software has an acceptable level of testing, it is reasonable to actually read the code by gaining understanding of a small portion of the code, then using the an automated refactoring tool to capture the discovery in the source document. (Read by Refactoring, devised by Arlo Belshee)</p>
<p>Reading the source code can also provide insights into the problem domain, depending on whether the domain information is well embedded in the source. As we learn to actively read our source code and add insights in place, domain knowledge can be embedded into the test and production source, which will lead the next developer to ask fewer questions like “what does 5 mean, and why are we checking if it is in the list” and more questions like “why do we no longer support feature x”.</p>
<h3 id="learning">Learning</h3>
<p>As developers settle into new positions at work, they must learn about business problems, and how the code solves those problems. There are four things developers spend a significant amount of time learning: technical foundations, problem space concerns, team-specific code patterns, team politics.</p>
<p>Technical foundation knowledge is the kind of knowledge which is used to become more effective creators of written logical documents. Technical foundations do not necessarily make source documents better, instead they provide the means to create source documents at all.</p>
<p>Problem space concerns are what the business cares most about. Combining an understanding of technical foundations, and the problem space, software developers can create a solution to the problem. The solution may not be right, and the code may not be immediately coherent, but these are the core to developing a first-pass software solution.</p>
<p>A parallel to the problem space is team-specific code patterns. Code patterns may be agreed upon coding standards like indentation, naming conventions, etc, or they may be more involved, like a common structure for microservices, including reuse of shared code. The problem space and the team-specific code patterns are two sides of the same coin – one serves the business, the other serves the team. When one or the other is missing, any developer would be at a significant disadvantage when working with a team.</p>
<p>Finally, we all must learn team politics. Regardless of how friendly and accommodating the developers in a team may be, there is a dynamic which has developed organically. To work effectively within a team, it is critical that all developers learn where it is okay to exert pressure, and where it is not.</p>
<p>Although these may not, on the surface, seem like software-developer problems, they are, at their core, the things we must learn about and adjust for on a daily basis.</p>
<h3 id="teaching">Teaching</h3>
<p>Just as developers on a team learn from one another, and the code, they also teach. Teaching comes in the form of tests, production source, documentation, human interaction, and communication. Teaching pervades everything we do as we develop software.</p>
<p>It has been said, there can be good design, and bad design, but there is never “no design”. In much the same way, there is never “no teaching”. People are social creatures and we take cues from people around us whether there was intent or not. Many norms have proliferated simply because nobody thought to say “hey, don’t actually do that”.</p>
<p>The source code we write provides instruction. When people read the source code which already exists in a project, they will infer information. There are assumptions made about style, content, problem space, etc.</p>
<p>In the same way, our actions instruct those around us. This means that when we act without intent or care, it unintentionally informs the people around us. Actions teach about social norms. Those norms will make their way into the source code whether we want it or not.</p>
<blockquote>
<p>A system will mirror the communication structure of the organization which made it – Mel Conway</p>
</blockquote>
<p>As developers we must be aware of, and use our skills of instruction as best we can. The people around us depend on us to be honest about our intent, and consistent with our behaviors. They depend on the code to reflect the way things are best done. They rely on clear understanding of the problem space and what we are doing to serve the business and the people who rely on our solutions.</p>
<h3 id="communicating">Communicating</h3>
<p>We talk about things all the time. Some of us talk too much and listen not enough. Nevertheless, what we need is real, rich communication. Communication is not merely talking, it is listening, synthesizing, and conveying fresh information.</p>
<p>If we consider synthesis as part of real communication about building software, it means we rely on other skills. One important skill is <strong><em>understanding</em></strong>. This means, in order to effectively communicate with someone about the solution being built, we must have a certain level of skill regarding understanding.</p>
<p>I’m not going to dive into recall at the moment, but understanding and recall go hand in hand. The entire process of communicating effectively, in a way that can be received by the people you’re communicating with, requires you be able to recall information, and actively understand how it relates to the communication at hand.</p>
<h3 id="understanding">Understanding</h3>
<p>Understanding is not a state of being, but an activity we undertake every time we interact with the software we build and support. Understanding is an active behavior centered on thinking about, chunking, and reorganizing the information we need to consider in order to build software effectively.</p>
<p>Understanding includes design and architectural patterns, testing approach (though not writing tests), domain concepts and domain driven design, and more. The most important takeaway here, is understanding does not actually include doing. Understanding involves looking at the source projects and evaluating how they are constructed, and for what purpose. It is the point at which problem domain understanding and technical knowledge meet.</p>
<p>By viewing understanding as an active engagement in teasing apart the software, we can also use this as a jump-off point for improving how we approach our understanding. Rather than understanding being a static state, it is a skill, which involves discovering information and reorganizing it into manageable chunks for consideration. This process of discovery and reorganization is a skill which can be developed over time.</p>
<h2 id="now-what">Now What?</h2>
<p>This was kind of a rambling round-up of the six aspects I have spotted in software development. This is unlikely to be the best write-up since there is so much discovery left to do. Nevertheless, once I found I was staring at six interrelated constituents of a larger system, many of the challenges developers struggle with became clear.</p>
<p>Some developers struggle to identify the “most important things to know”. This likely comes from one of a few potential reasons:</p>
<ul>
<li>not understanding that learning is an incremental discovery path</li>
<li>not understanding that different skills impact outcomes in different ways</li>
<li>not understanding that there is no single discrete skill which will make or break a developer on their career journey</li>
</ul>
<p>These 6 aspects are merely a lens we can use to evaluate where we, or others on our team, may be struggling. Moreover, there are complementary, and augmenting aspects. This means, if someone is struggling with reading code, it may mean the way code is written may be introducing a challenge. On the other hand, it may mean there is a learning gap, so we need to use our teaching skills.</p>
<p>Like any system, there is no single path to improvement, but there may be indicators of ways we can budge the needle without needing to spend a significant amount of time and effort to get people where they need to be next.</p>
<p>I hope this provides some usable insight which helps you and your team to become a little better than you were before. I’m really excited about what comes next with this all, and I hope we can discuss it soon!</p>Chris SteadThere is a sense of click-bait, and one of the most common forms is n-best lists. These are the 10 best basket weaving solutions on the market. Here are the 5 best practices of highly successful cat herders. Vampires HATE these 3 things do them to stay safe in your parking garage. They are right there. You almost want to click them to read more, right?Accommodation: Why We Bikeshed2021-05-18T01:00:00-07:002021-05-18T01:00:00-07:00http://chrisstead.net/programming/accommodation-theory/sociolinguistics-of-code/sociotechnical-systems/2021/05/18/accommodation-why-we-bikeshed<p><strong><em>Bikeshedding</em></strong><sup>1</sup> – that never-ending debate about a material disagreement – is so commonplace in the software industry we actually have parables about it. What’s more, I have actually seen people launch into meta-bikeshedding where they actually end up in an argument about what the original bikeshedding was about.</p>
<p>Two of the most common topics I have seen people bikeshed in the JavaScript community are indentation preference, and semicolon preference. Articles are referenced, appeals to reason are made. Some people even purport their position is supported by scientific discovery. In the end, though, it’s characterized as a matter of opinion.<!--more--></p>
<p>This is the classic story of the bikeshed, and the origin of it’s name:</p>
<blockquote>
<p>A nuclear reactor is being built. Technical specs are presented and agreed upon. Then the topic of a shed for cyclists to park their bikes arises. The location is agreed upon, but the color is an issue. Every person in the room has an opinion on the color of the bikeshed, and an argument ensues.</p>
</blockquote>
<p><em>This story actually characterizes all bikeshed arguments as a matter of opinion</em>. The claim is, all people have opinions, and it is hard to get consensus on pure opinion. What if all bikesheds, however, were not created equal?</p>
<h2 id="source-of-preference-disagreement">Source of Preference Disagreement</h2>
<p>Each person in a team comes from a different background. Even if one person “shares the same stack” as another, teams in various companies have differing norms regarding code style, structure, and even naming. People also differ in level of experience. These factors, among others, will impact how someone writes their code.</p>
<p>A common difference among developers on the same team is their history with a mix of languages which may or may not be related to the language at hand. This language or platform difference will affect how people expect to scan code, which can lead to preferences which enhance their ability to work effectively.</p>
<p>Let’s consider two people, Sean and Brenda, who are working in a NodeJS application codebase. Sean comes from a background of working in Python. He is used to the indentation requirements defined by the Python parser, frequently writes bare functions which are not attached to a class, and expects there to be no semicolons at the end of lines. Brenda, on the other hand, has a background in Java. She is most comfortable with classes, methods, loose indentation and strict semicolon requirements.</p>
<p>As Brenda works, day to day, she will often add semicolons into the code, when they are missing. She codes, almost exclusively, in class structures. Brenda has heard that the JavaScript community tends to prefer 2-space indentation, so this is the convention she uses. Meanwhile Sean often goes through removing semicolons he encounters and reformatting everything to have exactly 4 spaces of indentation. As you might imagine, Sean and Brenda bump into each other in the codebase a lot.</p>
<p>Though these things may seem superficial, Sean and Brenda clearly have divergent code styles. Since these two programming styles are centered on a common <strong><em>stylistic feature</em></strong><sup>2</sup> of the code there is a constant overlap of concerns. As you might imagine, Sean and Brenda both feel like they are not being respected by the other, frequently.</p>
<h2 id="accommodation">Accommodation</h2>
<p>Sociolinguistics has a concept called <strong><em>accomodation theory</em></strong><sup>3</sup> which is devised to provide insight into why people choose to either converge or diverge regarding their manner of speaking. The way people communicate – including dialect, style, formality, etc. – conveys information about the social group with which they most closely align.</p>
<h3 id="convergence">Convergence</h3>
<p>When people converge on a shared speech pattern – called <strong><em>speech convergence</em></strong><sup>4</sup> –, it can generate a sense of shared belonging. Each person is signaling to the other that they are respected and valued – each person may feel they are viewed as worthy of respect, understanding and trust.</p>
<p>In the same way, when people converge on similar coding styles there is a shared sense of agreement and belonging to a team or group. This sense of belonging can improve both in-code, and in-person communication. It fosters a sense of community which can lead to the developers seeking shared understanding.</p>
<h3 id="divergence">Divergence</h3>
<p><strong><em>Speech divergence</em></strong><sup>5</sup> can create a sense of <strong><em>othering</em></strong><sup>6</sup>. There may be numerous reasons speech is diverging, such as providing insights into a cultural norm, or offering a sense of acceptable behavior in a given setting. Ultimately, however, if hints at social expectations are not at play, speech divergence may be used to communicate a difference in group association. A common example is using speech to communicate class association.</p>
<p>When we diverge in code style, even if it is not intended, others may interpret the divergence as a hostile action. Divergent style, especially when applied to a source document without discussion, may elicit a sense of othering. Folks from different backgrounds may feel at odds because they sense the other person is not respecting their experience and group association.</p>
<h2 id="the-bikeshed">The Bikeshed</h2>
<p>If we look at the bikeshedding which happens between developers in meeting rooms across the world through the lens of accommodation theory, it reveals a different picture. No longer are developers fighting over something that is “mere opinion”. Instead, <strong>developers are saying they are not feeling included in the group</strong> when people push back on their code style. The message they hear is, “you are not worthy of consideration in this matter, you are not part of the group”.</p>
<p>With this framing, it becomes much more obvious why developers are so keen to fight for their preferred style of coding. They want to feel people are willing to converge toward their preference, which communicates respect for their past experiences. If Sean and Brenda were to sit down and discuss their backgrounds and where their styles arose, it would likely become easier to arrive at an acceptable shared style.</p>
<h2 id="closing">Closing</h2>
<p>I don’t have a formal study to support my hypothesis. Given the nature of human communication and the inclination for people to feel personally attached to their style of communication, it seems like a reasonable conclusion that folks would unconsciously feel a sense of othering in the absence of convergence toward a familiar coding style.</p>
<p>Ultimately, however, experience is the most likely motivator for coding style and practice. When coding practice bikeshedding begins, it may be worth exploring the background which led people to their current preferences. The nature of the conversation about seeking a shared understanding is welcoming to start, and it generates real understanding and empathy in the team. This <strong>understanding can guide us toward convergence on a working agreement regarding style and practice, helping all developers on the team feel more connected</strong>, making it easier to share and support ideas.</p>
<p><strong><em>Resources</em></strong></p>
<ol>
<li>Parkinson’s Law of Triviality <a href="https://en.wikipedia.org/wiki/Law_of_triviality">https://en.wikipedia.org/wiki/Law_of_triviality</a></li>
<li>Style (Sociolinguistics) <a href="https://en.wikipedia.org/wiki/Style_(sociolinguistics)">https://en.wikipedia.org/wiki/Style_(sociolinguistics)</a></li>
<li>Accommodation Theory (Communication Accomodation Theory or CAT) <a href="https://en.wikipedia.org/wiki/Communication_accommodation_theory">https://en.wikipedia.org/wiki/Communication_accommodation_theory</a></li>
<li>(Speech) Convergence <a href="https://en.wikipedia.org/wiki/Communication_accommodation_theory#Convergence">https://en.wikipedia.org/wiki/Communication_accommodation_theory#Convergence</a></li>
<li>(Speech) Divergence <a href="https://en.wikipedia.org/wiki/Communication_accommodation_theory#Divergence">https://en.wikipedia.org/wiki/Communication_accommodation_theory#Divergence</a></li>
<li>Othering (Philosophy) <a href="https://en.wikipedia.org/wiki/Other_(philosophy)">https://en.wikipedia.org/wiki/Other_(philosophy)</a></li>
</ol>Chris SteadBikeshedding1 – that never-ending debate about a material disagreement – is so commonplace in the software industry we actually have parables about it. What’s more, I have actually seen people launch into meta-bikeshedding where they actually end up in an argument about what the original bikeshedding was about.Naming Things, Part 4: Classes as Context2021-04-29T01:00:00-07:002021-04-29T01:00:00-07:00http://chrisstead.net/programming/human-centered-source/design/names/2021/04/29/naming-things-part-four-classes-as-context<blockquote>
<p>This is part 4 of a multi-part series on naming things. <a href="http://chrisstead.net/programming/human-centered-source/design/names/2021/03/25/naming-things-part-3-using-methods-for-context.html">part three will be useful</a></p>
</blockquote>
<p>Names are pesky little beasts. No single name exists without context<sup>1</sup>. This can be a disadvantage when names are unclear, abbreviated, or accidentally related to the surrounding context. On the other hand, if we understand that all names exist within some context, we can more carefully select the intention both of the name and the surrounding context for the name itself.</p>
<p>Long names can be a smell and, as we explored in a previous post<sup>2</sup>, we can do a little back of the envelope exploration and uncover a possible <strong><em>theme</em></strong> for the work being described in our source. Once we have identified a thematic word<sup>3</sup> or phrase, we can lift that aspect from the current name and use it to contextualize the source at a higher level.<!--more--></p>
<p>In other words, where we were able to lift context from a variable name and use it to contextualize work within a function, we can also lift context from a method, or property and use it to contextualize all of the work within our class.</p>
<h2 id="contextual-class-names">Contextual Class Names</h2>
<p>When last we saw our code sample, it had gone from a collection of language syntax and magic values to a function with context built into the name. Just as a reminder, here’s where we left it:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">throwIfBoxTooFull</span><span class="p">(</span><span class="nx">addedWidgets</span><span class="p">,</span> <span class="nx">maximumWidgetCount</span><span class="p">){</span>
<span class="kd">const</span> <span class="nx">tooManyWidgets</span> <span class="o">=</span> <span class="nx">addedWidgets</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">maximumWidgetCount</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">tooManyWidgets</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Exceeded widget max</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The body of our function largely expresses our intent, though in a future post, we will look at capturing the essence of our comparison and building a language structure around it to finish our abstraction of function constituents<sup>4</sup>.</p>
<p>Near the end of part three, we uncovered the primary theme of our function is the box. Given the widgets are incidental, regarding whether a box is too full – a box could really hold anything – our <strong><em>object of interest</em></strong> is most likely the box<sup>5</sup>.</p>
<p>The name of our function – which could, just as easily, be a method – provides us with everything we need to capture and lift the contextual element. This lifting would produce a transformation like the following:</p>
<p><code class="highlighter-rouge">throwIfBoxTooFull</code> -> <code class="highlighter-rouge">Box</code> (object of interest), <code class="highlighter-rouge">throwIfTooFull</code> (contextualized method)</p>
<p>This <strong><em>contextual lifting</em></strong> arms us with everything we need to build our new class:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nx">Box</span> <span class="p">{</span>
<span class="nx">throwIfTooFull</span><span class="p">(</span><span class="nx">addedWidgets</span><span class="p">,</span> <span class="nx">maximumWidgetCount</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">tooManyWidgets</span> <span class="o">=</span> <span class="nx">addedWidgets</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">maximumWidgetCount</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">tooManyWidgets</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Exceeded widget max</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="understanding-what-were-reading">Understanding What We’re Reading</h2>
<p>It’s worth noting that we can continue to make sense of the method name, i.e. <code class="highlighter-rouge">throwIfTooFull</code> even with the explicit “box” constituent removed. This is because our class definition carries a broader context which we naturally associate with other aspects of what we are reading.</p>
<p>For the sake of maintaining a shared vocabulary, we can call this <strong><em>source anaphora</em></strong>. This means we take the previously declared context or object of interest, and apply it to future, related communication. <strong><em>Anaphora</em></strong><sup>6</sup> is the core of how humans make sense of what may otherwise be unclear<sup>7</sup>.</p>
<p>This behavior of recalling context is what makes a refactoring from method parameters to properties a meaningful choice. By looking back to the first naming post, we have values we can insert here, so our refactoring follows:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nx">Box</span> <span class="p">{</span>
<span class="nx">addedWidgets</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">maximumWidgetCount</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span>
<span class="nx">throwIfTooFull</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">tooManyWidgets</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">addedWidgets</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="k">this</span><span class="p">.</span><span class="nx">maximumWidgetCount</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">tooManyWidgets</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Exceeded widget max</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In this example, all of the names which reside within the <code class="highlighter-rouge">Box</code> class are contextualized by the class name. We interpret this code in the following way:</p>
<ul>
<li><code class="highlighter-rouge">addedWidgets</code> – widgets added to the box</li>
<li><code class="highlighter-rouge">maximumWidgetCount</code> – maximum count of widgets that fit in the box</li>
<li><code class="highlighter-rouge">throwIfTooFull</code> – throw (an error) if the box is too full</li>
<li><code class="highlighter-rouge">tooManyWidgets</code> – too many widgets in the box</li>
</ul>
<p>There is a clear sense of the relation between the widgets we are concerned with and the box which contains them. Even the variables within the method maintain a connection to the broader context of the box, though the connection is likely carried through binding rather than source anaphora.</p>
<h2 id="wrapping-things-up">Wrapping Things Up</h2>
<p>By lifting context to higher levels as is appropriate, we can start to capitalize on the way people interpret natural language, making our code both more explicit regarding intent, while reducing the need to be explicit at each line.</p>
<p>Another interesting phenomenon emerges, which is caused through the broadening of our context. Some methods, properties, and variables may become less clear, even seeming like a non-sequitur in the larger document. This smell may be an indicator that either, we have lifted the wrong context, or these source constituents are misplaced, and may belong elsewhere. Though worth noting, this “wrong context” smell is something best left to be explored in the future.</p>
<p>At this point, our context-lifting journey has largely come to an end, though there is always more to discover and learn as you work through your source code. Look for context clues. Lift shared context into higher-level structures. As this refactoring work is done, your code should become clearer and more obviously related to the problem space. Experiments are worthwhile, so if you discover your code clarity is suffering, you can always fall back to an earlier position and reevaluate.</p>
<p>Happy naming!</p>
<p><strong><em>References</em></strong></p>
<ol>
<li>Why Worry About Names? <a href="http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/04/27/why-worry-about-names.html">http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/04/27/why-worry-about-names.html</a></li>
<li>Naming Things Part 3: Using Methods for Context <a href="http://chrisstead.net/programming/human-centered-source/design/names/2021/03/25/naming-things-part-3-using-methods-for-context.html">http://chrisstead.net/programming/human-centered-source/design/names/2021/03/25/naming-things-part-3-using-methods-for-context.html</a></li>
<li>The meaning of “word” in this case is intentionally vague, because it is likely more familiar to the reader. In reality what we will uncover will be more reflective of a morpheme, which encapsulates something about our source, and problem domain. (morpheme: <a href="https://en.wikipedia.org/wiki/Morpheme">https://en.wikipedia.org/wiki/Morpheme</a>)</li>
<li>Constituent <a href="https://en.wikipedia.org/wiki/Constituent_(linguistics)">https://en.wikipedia.org/wiki/Constituent_(linguistics)</a></li>
<li>Understanding of natural language and what is meant (at face value) by an utterance is known as semantics, which we will explore in another post. (semantics: <a href="https://en.wikipedia.org/wiki/Semantics">https://en.wikipedia.org/wiki/Semantics</a>)</li>
<li>Anaphora <a href="https://en.wikipedia.org/wiki/Anaphora_(linguistics)">https://en.wikipedia.org/wiki/Anaphora_(linguistics)</a></li>
<li>Understanding language in context is explored in the linguistic discipline of pragmatics. <a href="https://en.wikipedia.org/wiki/Pragmatics">https://en.wikipedia.org/wiki/Pragmatics</a></li>
</ol>Chris SteadThis is part 4 of a multi-part series on naming things. part three will be usefulWhy Worry About Names?2021-04-27T01:00:00-07:002021-04-27T01:00:00-07:00http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/04/27/why-worry-about-names<p>In every brownfield project I have ever worked on – and I have worked on a fair few – there is a common pattern I find. Developers either name their variables incomprehensibly, or they avoid using variables at all. Chains of function calls and expressions which stream across the screen and off the right side are the norm.</p>
<p>This is in no way an indictment of the developers who were working on the code. In fact, I assume they applied their knowledge in the best way they knew how at the time they were developing. Often developers are not armed with the knowledge they need to write stable software, or coherent source code.</p>
<p>Eric Evans addressed this problem from one side in his book, <em>Domain Driven Design</em>, as he talks about going to where the users are to uncover the way they talk about the work they do. He defines things like <strong><em>bounded context</em></strong>, and <strong><em>ubiquitous language</em></strong> (which is an extension of a <strong><em>lexicon</em></strong>), and late in the book he covers ways to incorporate those discoveries into the software being built.</p>
<p>The challenge is, there is an assumption of incremental discovery, however, incorporation can happen late. This means software can either languish in development limbo as discovery is done, or it can go off the rails early, which makes it difficult to recover.</p>
<p>What we really need is a tool <strong>right now</strong> which helps us iterate toward a better solution while we do the context and language discovery which needs to be done.<!--more--></p>
<h2 id="whats-in-a-name">What’s In a Name?</h2>
<p>Names in natural language are things like banana, fork, Bob, and Millicent. We designate a name for people, places, and things in order to be specific about who or what we are talking about. These names are, for our purposes, abstractions over a much more complicated topic.</p>
<p>“Banana” provides a lot of context:</p>
<p>A fruit
Thick skin
Starchy
Sweet
Yellow
Gets brown spots as it goes through ripening</p>
<p>There is a lot we know about a banana empirically without having any deeper technical knowledge at all. We don’t need to know about any botanical classifications, potassium content, radioactivity, or the fact that the common banana comes from a monoculture. In fact, if you started listing those items first, many people would give you a strange look.</p>
<p>Somehow, this kind of technical language manages to worm its way into our source code. Rather than revealing the things we need to understand what we are abstracting, we encode the technical underpinnings into a name. Instead of a name like <code class="highlighter-rouge">veryRipeBanana</code>, we get names like <code class="highlighter-rouge">softFruitWithBrownSpots</code>. That is, if we get a name.</p>
<p>Sometimes we just get this:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">.</span><span class="nx">eat</span><span class="p">(</span><span class="k">new</span> <span class="nx">Fruit</span><span class="p">({</span>
<span class="na">characteristics</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">soft</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">brown spots</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">starchy</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">radioactive</span><span class="dl">'</span><span class="p">],</span>
<span class="na">classification</span><span class="p">:</span> <span class="dl">'</span><span class="s1">edible</span><span class="dl">'</span>
<span class="p">}));</span>
</code></pre></div></div>
<p>Though we know something about the action (eat) and something about the food (fruit) there is a lot we lose. Often names in our code are treated like names in natural language: as nouns meant for simply declaring something exists.</p>
<h2 id="names-arent-names">Names aren’t Names</h2>
<p><strong><em>Names are carriers of the value and intent we communicate to the reader.</em></strong></p>
<p>Instead of thinking of names as nouns (Ralph, Jenny, cucumber, EmpireStateBuilding), we can reframe them as parts of a larger written work. Source code is both a set of instructions for program execution, and communication to the developers who interact with it. This means names are not simply nouns, verbs, adjectives, and the like. Names are best considered as meaningful phrases which should be sensible within the larger document context.</p>
<p>If we consider names, first, within the context of what they are naming, we can communicate a significant amount of information to the reader. Functions can carry information when they are written as verb phrases. The same can be said for object properties which can be given noun phrase names reflect some aspect of a larger whole. Local variables can also do this kind of communication work by reflecting the outcome of work done, or reflecting the intermediate state of a larger algorithm.</p>
<p>Each name we choose provides broader insight into the software as a whole. This means we can use what we know of the real world and the problem at hand to bake context deep into the source of our software.</p>
<p>Since living software is an evolving thing, we will learn new things about the problem we are solving as we work. This learning process will lead to discovering names which more closely reflect the history and intent of the software we create.</p>
<p>Names make source documents human documents.</p>
<h2 id="names-are-cumulative">Names are Cumulative</h2>
<p>No single name in source code actually lives alone. Even if our software is simply the definition of a single variable in a Python file, <code class="highlighter-rouge">my_name = "Chris"</code> there is still the real world which informs us of what this program does. When the source code increases in size and complexity, names actually provide context which leads to better recall of both the language used in the documents, as well as the surrounding real-world context.</p>
<p>This context-driven recall is a noted phenomenon studied by linguists and cognitive scientists. There are several factors which come into play, two of which we can use immediately – context and frequency of use. When we center the names and language in our source documents around the words we use when talking about the problem, we bake in the ability for people to quickly recall and use domain knowledge which is related to the problem our software solves.</p>
<p>What this means is, each file name, class or module name, method or function name, variable, and <strong><em>thematic group</em></strong><sup>1</sup> we create leads us, and other developers, toward understanding the problem rather than simply the nuts and bolts of an algorithm. Moreover, the more we consider what the document communicates, the faster programmers will be able to gather information from reading it.</p>
<h2 id="names-are-language">Names are Language</h2>
<p>One of the most important things we can impart with a name is the ability to read code aloud and talk about it like humans. The natural state of human communication is spoken language. We learn language first this way. Written language is an invention which, historically, acts as a symbol representing other types of human communication – speech, gesture, and expression. This takes us full circle to natural language.</p>
<p>If we consider the following code:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>const finalTrs = trs.filter(x => x.id > 5);
</code></pre></div></div>
<p>We get no new information by reading it aloud. In fact it is written in such a way that reading it aloud might actually make it harder to understand than simply reading it silently, as a collection symbols.</p>
<p>If we write code this way instead:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>const lastFakeRequirementId = 5;
const isRealRequirement = requirement => requirement.id > lastFakeRequirementId;
const realTestRequirements = allTestRequirements.filter(isRealRequirement);
</code></pre></div></div>
<p>The code becomes longer, but it also communicates the information we need to know in order to quickly spin up on the local context and understand why choices were made. This kind of naming leans heavily into the thing people understand best: natural language.</p>
<h2 id="so-why-worry-about-names">So, Why Worry About Names?</h2>
<p>Those of us who worry about names do so because names are language. Names communicate what bare programming language symbols cannot: problem domain, context, a shared lexicon, and history.</p>
<p>High quality names are much like good writing – they tell a story. We will not always get names right on the first pass, but that’s okay. As we learn, we can update our names to form a better picture. We can capture discoveries as we have them, and communicate the why, instead of how, to people as our code base grows.</p>
<p>Names alone are not software, but they make the software source more human.</p>
<p><strong><em>References</em></strong></p>
<ol>
<li>Thematic Grouping <a href="http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/03/27/the-theme-of-your-code.html">http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/03/27/the-theme-of-your-code.html</a></li>
</ol>Chris SteadIn every brownfield project I have ever worked on – and I have worked on a fair few – there is a common pattern I find. Developers either name their variables incomprehensibly, or they avoid using variables at all. Chains of function calls and expressions which stream across the screen and off the right side are the norm.Reading Source Code, Reading Natural Language2021-04-06T01:00:00-07:002021-04-06T01:00:00-07:00http://chrisstead.net/programming/software-linguistics/research/2021/04/06/reading-source-code-reading-natural-language<p>In a previous blog post<sup>1</sup> I talked about an article claiming that reading source code was not like reading natural language. The original post referred to an article from “Science Daily”<sup>2</sup>, however there were far too many details missing, so I could only speculate on what the research said, how it was conducted, etc.</p>
<p>Last night I looked up a writeup on the original study<sup>3</sup>, and I found it to be rather disappointing. Though I haven’t used an functional magnetic resonance imaging (fMRI) device for any purpose, let alone the purposes of mapping brain activity, I can (and will) use other evidence to propose the founding notion of their study was flawed. This foundational flaw, in my opinion, invalidates the discovery which was done.</p>
<p>Let’s explore.<!--more--></p>
<h2 id="sample-code-and-control-writing-sample">Sample Code and Control Writing Sample</h2>
<p>There has been extensive research and mapping done on the brain when someone is reading a natural language passage. I will opt to skip providing a reference for this since a simple search will turn up a tremendous amount of information presented by psycholinguists, and cognitive scientists.</p>
<p>The known mapping of language and brain activity is what was used as a basis for the study done for the paper I referenced earlier<sup>3</sup>. Of course, the issue at hand is they did not generate their own control for their study. By simply assuming that their work was representative of an acceptable comparison to other natural language mapping, they simply used existing maps.</p>
<p>Now, if we review their source code, we can see the task which was presented to the subjects of the study:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static void main(String[] args) {
String word = "Hello";
String result = new String();
for (int j = word.length() - 1; j >= 0; j--)
result = result + word.charAt(j);
System.out.println(result);
}
</code></pre></div></div>
<p>The source, as presented above, is presented as closely as possible to the text which was used in the study according to the paper, including the lack of syntax highlighting. We will return to the highlighting issue later.</p>
<p>The stated goal of the subjects was to read this text and declare what the outcome would be. Of course, determining the outcome of a program is not the same as simply reading a selection of natural language. Let’s consider the following passage:</p>
<blockquote>
<p>In a hole in the ground there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to eat: it was a hobbit-hole, and that means comfort.</p>
</blockquote>
<p>Though the supplied text is from “The Hobbit”, and is evocative of fantastic imagery, there is no expectation that we need to do any computational evaluation of this text. In fact, there is no computation to be done. Instead this is simply text which describes a scene.</p>
<p>Suppose, instead, our sample text were more like the following:</p>
<blockquote>
<p>Sally is three times as old as Billy. Billy will be half Sally’s age in a year. How old is Billy?</p>
</blockquote>
<p>Now, let’s suppose the subjects were asked to supply a computational result to this question. Would their brain activity match that of the person reading the selection from “The Hobbit”? Almost certainly not.</p>
<p>Why?</p>
<p>There is a computation expectation set in the second text selection which is not there in the first. Though the second selection is natural language, there is a mathematical component which demands that someone evaluate the text beyond just simply reading it. In fact there is an answer which would be considered correct.</p>
<p>I would argue, without control text like our age problem, the research is not representative of a person in an equivalent natural language setting. The computational nature of the selected text is critical for ensuring we are accurately comparing equivalent activity mapping.</p>
<h2 id="representative-source-code">Representative Source Code</h2>
<p>Suppose we were to select source code which represents well-abstracted computation, which is typically how people process talking about things like making a sandwich, or replacing a light bulb, we might have source which would look like the following:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static void reverseAndPrintAWord(String word) {
String reversedWord = reverseWord(word);
printToScreen(reversedWord);
}
</code></pre></div></div>
<p>This text is significantly less computational in nature, and reflects the kind of code people might encounter in the wild, especially as a professional developer. Of course, someone might say this text is too trivial to be representative of reading source code, however, it is source code which represents computation which will be done.</p>
<p>In this case, if someone were asked to state what this code does, even with a very limited background in programming, they would likely say it reverses a word and prints it to the screen. Although this is source code, it is more akin to natural language than the more computationally complex source taken from the original paper.</p>
<p>In fact, even without syntax highlighting there is sufficient information here that the noise at the front of the function definition, <code class="highlighter-rouge">public static void</code>, could be ignored, even by a novice programmer.</p>
<p>I’m not confident that this would map to the same centers of the brain as natural language, but the presence of clear natural language in the source code leads me to believe the language centers are much more likely to be triggered.</p>
<h2 id="syntax-highlighting-and-code-semantics">Syntax Highlighting and Code Semantics##</h2>
<p>The subjects of the study were presented with source code written in black and white, and asked to interpret it. This is, once again, not representative of the way that professional programmers work in daily life. It is most common to see a professional programmer working in a specialized source code editor, or an Integrated Development Environment (IDE).</p>
<p>If we consider code which is highlighted as it is in an IDE, we would be presented with the following:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">word</span> <span class="o">=</span> <span class="s">"Hello"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">();</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">word</span><span class="o">.</span><span class="na">length</span><span class="o">()</span> <span class="o">-</span> <span class="mi">1</span><span class="o">;</span> <span class="n">j</span> <span class="o">>=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">j</span><span class="o">--)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="o">+</span> <span class="n">word</span><span class="o">.</span><span class="na">charAt</span><span class="o">(</span><span class="n">j</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">result</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>This coloring reduced <strong><em>cognitive load</em></strong><sup>4</sup> for the reader, which means there are <strong><em>semantic markers</em></strong><sup>4</sup> which are presented in highlighted code which the subjects of the study were not given. These semantic markers provide insight into how to best read and comprehend the source code provided.</p>
<p>Moreover, if we were to review our abstracted source code, adding syntax highlighting, we can see the compiler-related information at the beginning of the sample can be easily ignored and skipped, allowing the reader to jump quickly to the semantically rich function name.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">reverseAndPrintAWord</span><span class="o">(</span><span class="nc">String</span> <span class="n">word</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">reversedWord</span> <span class="o">=</span> <span class="n">reverseWord</span><span class="o">(</span><span class="n">word</span><span class="o">);</span>
<span class="n">printToScreen</span><span class="o">(</span><span class="n">reversedWord</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Although a novice programmer may still read the leading <code class="highlighter-rouge">public static void</code> copy, they are likely to ignore it, knowing they are tasked with understanding the behavior within the body of the method, which <code class="highlighter-rouge">public static void</code> is not part of.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Though the study has merit regarding mapping the way someone interprets source code which is computationally rich, it is not, in my estimation, a representative study on whether reading source code is, actually, like reading natural language.</p>
<p>Perhaps the researchers would consider employing a professional developer with experience writing well-abstracted code if they chose to revisit the study. In all likelihood, there is little money in the research being done, so this paper, and those like it, are likely to stand as a testament that programmers reading code are not reading like they would had they encountered natural language.</p>
<p>Nevertheless, linguistically, I would contend there are significant gaps in the foundational assumptions made before conducting the study. I don’t have evidence that well-abstracted source code would actually trigger the same centers in the brain as natural language, nor do I have the means to support or reject a hypothesis regarding brain activity. Moreover, I don’t have any means to define a quantitative analysis of what it means to for code to be well-abstracted. Nevertheless, I to believe there is sufficient evidence in existing academic studies by cognitive scientists and linguists to show this study was not well-formed.</p>
<h3 id="addendum">Addendum</h3>
<p>There is an article about a small (~20 person) MIT study<sup>6</sup>, which nominally resolves some of my concerns, however, I’m uncertain that, even still, their study sufficiently considered the abstractions people have built in around names and words, especially when considering a scratch program which uses visual representations of meaning, which have no intrinsic linguistic value whatsoever. I’m concerned that there isn’t a deeper consideration for what well abstracted code might look like and whether code might more closely model natural language when abstracted in a similar fashion to natural language.</p>
<p><strong><em>References</em></strong></p>
<ol>
<li>“The Language of Software” <a href="http://chrisstead.net/programming/programming-languages/software/development/linguistics/2021/03/03/the-language-of-software.html">http://chrisstead.net/programming/programming-languages/software/development/linguistics/2021/03/03/the-language-of-software.html</a></li>
<li>“To the brain, reading computer code is not the same as reading language” <a href="https://www.sciencedaily.com/releases/2020/12/201215131236.htm">https://www.sciencedaily.com/releases/2020/12/201215131236.htm</a></li>
<li>“Understanding Understanding Source Code With Functional Magnetic Resonance Imaging” (PDF) <a href="https://www.cs.cmu.edu/~ckaestne/pdf/icse14_fmri.pdf">https://www.cs.cmu.edu/~ckaestne/pdf/icse14_fmri.pdf</a></li>
<li>“Cognitive Load Theory” (PDF) <a href="http://ndl.ethernet.edu.et/bitstream/123456789/31186/1/125.John%20Sweller.pdf">http://ndl.ethernet.edu.et/bitstream/123456789/31186/1/125.John%20Sweller.pdf</a></li>
<li>“Semantic markers” <a href="https://link.springer.com/article/10.1007%2FBF02380291">https://link.springer.com/article/10.1007%2FBF02380291</a></li>
<li>“Is computer code a language or math? MIT study uses brain scans for answers” <a href="https://bigthink.com/mind-brain/coding-language-brain">https://bigthink.com/mind-brain/coding-language-brain</a></li>
</ol>Chris SteadIn a previous blog post1 I talked about an article claiming that reading source code was not like reading natural language. The original post referred to an article from “Science Daily”2, however there were far too many details missing, so I could only speculate on what the research said, how it was conducted, etc.Source Modalities: Rules and Conditions2021-04-03T01:00:00-07:002021-04-03T01:00:00-07:00http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/04/03/source-modalities-rules-and-conditions<p>While analyzing and editing source code, much of the work to be done is rather straightforward. Many business applications are data stores with a user interface so a non-developer can manage the data.</p>
<p>Even these applications, however, introduce certain small complexities which tend to muddy the water. A subset of users need product codes to be handled in a way the system didn’t originally account for. Certain segments of the software must serve two distinct user types, which lead to very different workflows. A particularly common issue which arises is, sometimes data is incomplete or corrupted in a way that breaks the application.</p>
<p>All of these scenarios, and a multitude of others, require consideration of the rules which drive the system, and the choices which must be made to satisfy users. Source code which handles varied options, or things which must be is dealing in <strong><em>modality</em></strong><sup>1</sup>.<!--more--></p>
<h2 id="linguistic-modality">Linguistic Modality</h2>
<p>Modality in linguistics centers around language which deals in either necessary, or possible scenarios. <strong><em>Modal expressions</em></strong> generally include words like <em>must</em>, <em>should</em>, <em>could</em>, <em>might</em>, and <em>may</em>. This kind of language introduces the notion of <strong><em>possible worlds</em></strong><sup>2</sup>.</p>
<p>A possible world is a world which is complete and well defined within the scope of a particular modality. In other words, “my wife might have blue hair tomorrow” suggests there is a possible world where she will have blue hair, and another possible world where she may not.</p>
<p>Meanwhile, there is another modality where there is only one possible scenario. This modality is the necessity modality. The outcome, or state of being is necessary regardless of what may happen between now and the eventual end. E.g. “The winner of the contest must read the most books.” Regardless of who wins the contest, we know they read the most books. It is not stated what would happen if there were two people who read exactly the same number of books. Perhaps there is a sudden-death read-off. No matter what the outcome is the only possibility.</p>
<h2 id="source-modality">Source Modality</h2>
<p><strong><em>Source modality</em></strong> arises from the existence of <strong><em>rules</em></strong> and <strong><em>conditions</em></strong>. Rules are the semantic equivalent of necessity. Conditions are the semantic equivalent of possibility. Rules typically involve concepts like <em>validation</em>, <em>verification</em>, and <em>assertion</em>. Meanwhile conditions generally involve <em>decisions</em>, <em>changes of state</em>, and <em>value selection</em>.</p>
<p>We can see necessity arise from rules when reflecting on expectation the users must meet in order to successfully work within the provided software. A common example is “the user must log in to view their order status.” A modal expression jumps right out; “the user <em>must</em> log in.” This modal expression will end up in the code as a verification. When someone attempts to view an order status page, the software will need to verify an appropriate user is logged in.</p>
<p>Likewise possibility will emerge from user choices in the application, design patterns, and even data management. It’s common to have changes in the state of the application arise from actions the user takes when interaction with software. These state changes can introduce a chain of conditional events including triggering validation (rules, necessity), data management, resolution of bad, or missing values, or even a cascade of changes in the user interface itself.</p>
<h2 id="semantic-transparency">Semantic Transparency</h2>
<p>The big question is, why does it matter? In the end, conditional and Boolean logic is part and parcel of software development. Modality is just a fancy way of talking about conditionals.</p>
<p>To understand why modality matters, it’s worth exploring <strong><em>semantic transparency</em></strong><sup>3</sup>, or <strong><em>semantic opacity</em></strong><sup>3</sup> of source code.</p>
<p>If we looked at the following source code, we can see the two core types of modality playing out:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_user_name</span><span class="p">(</span><span class="n">user_id</span><span class="p">):</span>
<span class="n">user_record</span> <span class="o">=</span> <span class="n">get_user_record</span><span class="p">(</span><span class="n">user_id</span><span class="p">)</span>
<span class="k">if</span> <span class="n">user_record</span> <span class="o">==</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">Exception</span><span class="p">(</span><span class="s">"Invalid User ID"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">user_record</span><span class="o">.</span><span class="n">version</span> <span class="o"><</span> <span class="mi">2</span><span class="p">:</span>
<span class="k">return</span> <span class="n">user_record</span><span class="o">.</span><span class="n">name</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">format_name_by_culture</span><span class="p">(</span><span class="n">user_record</span><span class="p">)</span>
</code></pre></div></div>
<p>There are two conditionals in this piece of code, and each has a distinct semantic meaning. The first condition is a rule. If the record does not exist, the rule has been violated: the user ID was not valid. The second conditional was designed around versions of stored data. A user record may contain a valid value in the name field, or it may contain information which would make it possible to use name fields and a culture value to properly format a name.</p>
<p>Due to the collection of conditional blocks, and the distinct modality of each, this function has a few issues:</p>
<ol>
<li>It is just doing too much</li>
<li>It includes rule information</li>
<li>It includes data condition information</li>
</ol>
<p>Ultimately we would refer to this function as <strong><em>semantically opaque</em></strong>. By carrying too much information, and of disparate kinds, we lose the thread of meaning within the code. By understanding source modality, we can do a preliminary analysis of the source code:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_user_name</span><span class="p">(</span><span class="n">user_id</span><span class="p">):</span>
<span class="c1"># inappropriate state concern mixing
</span> <span class="n">user_record</span> <span class="o">=</span> <span class="n">get_user_record</span><span class="p">(</span><span class="n">user_id</span><span class="p">)</span>
<span class="c1"># Modality: Rule -- user_id is invalid if no record exists in the database
</span> <span class="k">if</span> <span class="n">user_record</span> <span class="o">==</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">Exception</span><span class="p">(</span><span class="s">"Invalid User ID"</span><span class="p">)</span>
<span class="c1"># Modality: Condition -- record data changed from version 1 to version 2
</span> <span class="k">if</span> <span class="n">user_record</span><span class="o">.</span><span class="n">version</span> <span class="o"><</span> <span class="mi">2</span><span class="p">:</span>
<span class="k">return</span> <span class="n">user_record</span><span class="o">.</span><span class="n">name</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">format_name_by_culture</span><span class="p">(</span><span class="n">user_record</span><span class="p">)</span>
</code></pre></div></div>
<p>Once we have done a quick analysis of the code at hand, the elements of the function become clearer, and we can apply techniques like <strong><em>thematic grouping</em></strong><sup>4</sup>, and broader refactoring.</p>
<h2 id="wrap-up">Wrap Up</h2>
<p>When we can name the sense of lost meaning in our source code, we can apply tools to begin untangling semantic issues in our program. By sensing semantically opaque code, we can search for themes and modalities. These code characteristics can help us understand both what the code is accomplishing and what the original intent may have been.</p>
<p>The next time you dive into an existing piece of code, think about how well you understand the underlying meaning. Are you looking at symbol soup, or is the source semantically transparent? Can you discern what the business domain, and context are? What do the conditional blocks look like? Perhaps there is modal information which can be discovered.</p>
<p><strong><em>References</em></strong></p>
<ol>
<li>“Modality (natural language)” <a href="https://en.wikipedia.org/wiki/Modality_(natural_language)">https://en.wikipedia.org/wiki/Modality_(natural_language)</a></li>
<li>“Possible World” <a href="https://en.wikipedia.org/wiki/Possible_world">https://en.wikipedia.org/wiki/Possible_world</a></li>
<li>“Transparency (linguistics)” <a href="https://en.wikipedia.org/wiki/Transparency_(linguistic)">https://en.wikipedia.org/wiki/Transparency_(linguistic)</a></li>
<li>“The Theme of Your Code” <a href="http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/03/27/the-theme-of-your-code.html">http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/03/27/the-theme-of-your-code.html</a></li>
</ol>Chris SteadWhile analyzing and editing source code, much of the work to be done is rather straightforward. Many business applications are data stores with a user interface so a non-developer can manage the data.The Theme of Your Code2021-03-27T01:00:00-07:002021-03-27T01:00:00-07:00http://chrisstead.net/programming/software-linguistics/human-centered-source/design/2021/03/27/the-theme-of-your-code<p>In the past 25 years, or so, it has become popular to consider high-level structure of programs in chunks defined by a group affectionately referred to as the “Gang of Four”. They wrote a book called “Design Patterns”<sup>1</sup> which laid out common patterns for solving well-understood problems in software.</p>
<p>There are many more patterns than those laid out in “Design Patterns”, but the idea still remains the same. The design starts, typically, at the module, or class level and goes up from there. Occasionally design will start at a function level, when the programming language allows for independent functions, but this is rather uncommon.</p>
<p>On the other hand, when looking at source code line-by-line, people often fall back to naming as a primary design strategy, and follow the convention of “put your variables as close to their use as possible”. Though this strategy makes sense contextually, since you can see the variable declared and defined near the use of the value.</p>
<p>Where we land when following common rules of thumb and patterns is a mix of large chunks of design, and small clusters of variables followed by use. This code is arguably better than code in which no design choices were made. However, we are overlooking a critical aspect of communicating in our code.<!--more--></p>
<h2 id="semantic-well-ordering-coherence-and-thematic-grouping">Semantic Well-Ordering, Coherence, and Thematic Grouping</h2>
<p>When written communication is created, it is common to group ideas together. We see this in popular writing, blogs (like this one) and even threads on Twitter. This grouping of concepts is essential for the <strong><em>cooperative principle</em></strong><sup>2</sup> to hold.</p>
<p>The cooperative principle, in the case of source code, will demand that <strong><em>thematic constituents</em></strong><sup>3</sup> are grouped together, and ordered in a way which supports either inductive, or deductive support of the overarching theme.</p>
<h3 id="the-cooperative-principle">The Cooperative Principle</h3>
<p>The cooperative principle reads as follows:</p>
<blockquote>
<p>Make your conversational contribution such as is required at the stage at which it occurs by the accepted purpose or direction of the talk exchange in which you are engaged.</p>
</blockquote>
<p>This is a really long way of saying “stay on topic”. An interesting aspect of the cooperative principle is, people typically follow it by default. In other words, people tend to collect contextual information from the communication at hand, and respond, on topic. Since people generally follow the cooperative principle, there are assumptions which follow.</p>
<ul>
<li>The speaker is saying something related to the topic at hand</li>
<li>The listener is in tune with the topic and maintaining a contextual sense of the current conversation</li>
</ul>
<p>All of this means that anyone reading written communication is going to assume there is an intended coherent structure. When any written communication violates this sense of coherence, it leads to a violation of the cooperative principle.</p>
<h3 id="semantic-well-ordering">Semantic Well-Ordering</h3>
<p>There is a core requirement that code be well-ordered with respect to execution. If code is not constructed in the correct order, execution will fail, or behave in unexpected ways. We can call this <strong><em>algorithmic well-ordering</em></strong>.</p>
<p>On the other hand, humans reading code will need indicators of what to expect from the source document as a communication medium. In order to understand passages of the code and quickly infer meaning, there must be a human-language related well-ordering which drives the uptake of contextual cues, and domain understanding. We can call this <strong><em>semantic well-ordering</em></strong>.</p>
<h3 id="coherence">Coherence</h3>
<p><strong><em>Coherence</em></strong><sup>4</sup> is the interrelation between units of text in a written communication. When writing is coherent it appears to be logically, and semantically consistent for the reader. This need for consistency and clarity is typically supported by the order in which information is presented.</p>
<p>Coherent code carries an additional requirement that each line, and expression be semantically well-ordered. Coherence cannot be achieved when the reader is required to constantly seek context-carrying source in order to understand the work at hand.</p>
<p>Coherence creates the link between the reader-listener, and the cooperative principle, meaning, the reader-listener will assume the position that the writer stayed on topic as well as they could manage. This means any reader-listener is going to seek connections between locally grouped units of text.</p>
<p>When the text is incoherent, either because of superfluous information, or the lack of semantic well-ordering, the reader-listener may infer meaning, or associate ideas incorrectly. This incoherence can lead to distraction, or misunderstanding of the written communication.</p>
<h3 id="thematic-grouping">Thematic Grouping</h3>
<p>Ideally our source code would all be coherent and carefully organized. As is the way, the world will have none of it. Source code often contains half-complete ideas, varied levels of abstraction, and inconsistent language. We can’t address all of this in one post, but we can look at how we can create more coherent code with <strong><em>thematic grouping</em></strong>.</p>
<p>A rule of thumb, mentioned earlier, is “keep your variable definitions as close to their use as possible”. This is a relatively rudimentary form of thematic grouping. In this particular case, the theme is the named value, and the way in which it is used. This theme is not particularly interesting, and may end up distracting the reader from the broader purpose of the code.</p>
<p>Thematic grouping is driven by a need for coherence which, in turn, arises from semantically well-ordered source code. This means, though a variable may live as close as possible to its use, this may not produce either coherent, or semantically well-ordered code. Let’s consider the following code:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_books_by_dr_seuss_paginated</span><span class="p">(</span><span class="n">current_page</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
<span class="n">row_limit</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">author</span> <span class="o">=</span> <span class="s">"Dr. Suess"</span>
<span class="k">return</span> <span class="n">Books</span><span class="o">.</span><span class="n">get_by_author</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">current_page</span><span class="p">,</span> <span class="n">row_limit</span><span class="p">)</span>
</code></pre></div></div>
<p>On the face, this code might seem rather tight and tidy. We are making a database query, and returning the result back to the caller. However, we introduced an incoherent element into our function, which the reader will seek to understand in the greater context. We can make the inappropriate element obvious through thematic grouping:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_books_by_dr_seuss_paginated</span><span class="p">(</span><span class="n">current_page</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
<span class="n">row_limit</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">author</span> <span class="o">=</span> <span class="s">"Dr. Seuss"</span>
<span class="k">return</span> <span class="n">Books</span><span class="o">.</span><span class="n">get_by_author</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">current_page</span><span class="p">,</span> <span class="n">row_limit</span><span class="p">)</span>
</code></pre></div></div>
<p>Here we can see the theme defined by the function name is “books, by Dr. Seuss, by page”. The thematic group, then, would be (page, author, database request). The variable <code class="highlighter-rouge">row_limit</code> is not thematically appropriate, and breaks the sense of coherence.</p>
<p>The coherence of the source text fails because our original code was not semantically well-ordered. By analyzing the lines, it can be argued that <code class="highlighter-rouge">row_limit</code> is semantically related to the database query, but is not related in any way to the name of the author. If we reorganize our code in a way which is still algorithmically well-ordered, we can produce semantically well-ordered code as well.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_books_by_dr_seuss_paginated</span><span class="p">(</span><span class="n">current_page</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
<span class="n">author</span> <span class="o">=</span> <span class="s">"Dr. Seuss"</span>
<span class="n">row_limit</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">return</span> <span class="n">Books</span><span class="o">.</span><span class="n">get_by_author</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">current_page</span><span class="p">,</span> <span class="n">row_limit</span><span class="p">)</span>
</code></pre></div></div>
<p>With this regrouping, we can see there are two distinct themes in this block of code:</p>
<ol>
<li>Books by Dr. Seuss, by page</li>
<li>Paginated request for books by an author, with a page size</li>
</ol>
<p>This new thematic grouping can guide us to a quick, sensible refactoring, creating a new function and reducing the <strong><em>cognitive load</em></strong><sup>6</sup> for the reader:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_books_by_author_paginated</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">current_page</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
<span class="n">page_size</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">return</span> <span class="n">Books</span><span class="o">.</span><span class="n">get_by_author</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">page</span><span class="p">,</span> <span class="n">page_size</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_books_by_dr_seuss_paginated</span><span class="p">(</span><span class="n">current_page</span><span class="p">):</span>
<span class="n">author</span> <span class="o">=</span> <span class="s">"Dr. Seuss"</span>
<span class="k">return</span> <span class="n">get_books_by_author_paginated</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">current_page</span><span class="p">)</span>
</code></pre></div></div>
<p>A little judicious rearrangement, and we have two blocks of code which maintain a clear theme, and coherent communication. Our function, parameter, and variable names all align with the intended work to be done. They communicate the correct abstraction level, and they make it easy for the reader to guess what they will find in the next bit of code.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Thematic grouping may not always lead to an immediate refactoring, aside from line order; this is especially common in <strong><em>legacy code</em></strong><sup>5</sup> where long methods may be unsafe to change. Simply reorganizing code into <strong><em>thematic groups</em></strong> will make it easier to understand the intent of the source code and do net positive work by increasing local coherence and reducing cognitive load.</p>
<p><strong><em>References</em></strong></p>
<ol>
<li>“Design Patterns: Elements of Reusable Object-Oriented Software” <a href="https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented-dp-0201633612/dp/0201633612/ref=mt_other?_encoding=UTF8&me=&qid=">https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented-dp-0201633612/dp/0201633612/ref=mt_other?_encoding=UTF8&me=&qid=</a></li>
<li>“Cooperative Principle” <a href="https://en.wikipedia.org/wiki/Cooperative_principle">https://en.wikipedia.org/wiki/Cooperative_principle</a></li>
<li>“Constituent (linguistics)” <a href="https://en.wikipedia.org/wiki/Constituent_(linguistics)">https://en.wikipedia.org/wiki/Constituent_(linguistics)</a></li>
<li>“Coherence” <a href="https://en.wikipedia.org/wiki/Coherence_(linguistics)">https://en.wikipedia.org/wiki/Coherence_(linguistics)</a></li>
<li>“Working Effectively With Legacy Code” <a href="https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052">https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052</a></li>
<li>“Cognitive Load Theory” <a href="https://www.mindtools.com/pages/article/cognitive-load-theory.htm">https://www.mindtools.com/pages/article/cognitive-load-theory.htm</a></li>
</ol>Chris SteadIn the past 25 years, or so, it has become popular to consider high-level structure of programs in chunks defined by a group affectionately referred to as the “Gang of Four”. They wrote a book called “Design Patterns”1 which laid out common patterns for solving well-understood problems in software.Naming Things Part 3: Using Methods for Context2021-03-25T01:00:00-07:002021-03-25T01:00:00-07:00http://chrisstead.net/programming/human-centered-source/design/names/2021/03/25/naming-things-part-3-using-methods-for-context<blockquote>
<p>This is part three of a multi-part series on naming things. <a href="http://chrisstead.net/programming/human-centered-source/design/names/2021/03/15/naming-things-part-the-second-simple-expressions.html">Part two will be useful</a><sup>1</sup>.</p>
</blockquote>
<p>When looking for the right name for something you can end up with a pretty long name. In part 2, we looked at capturing conditional context by extracting a simple expression, but the name was pretty long.</p>
<p>Long names can be problematic for code <strong><em>scannability</em></strong>. We can work to move the most important words to the front of the variable name, but once a name gets long enough, it begins to contribute to the wall of text we are working so hard to reduce.<!--more--></p>
<p>We can actually see this with the first name example in our sample code.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">exceededWidgetsPerBox</span> <span class="o">=</span> <span class="nx">addedWidgets</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">maximumWidgetsPerBox</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">exceededMaxWidgetsPerBox</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Exceeded widget max</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The name <code class="highlighter-rouge">exceededMaxWidgetsPerBox</code> is really long, and actually reduces the ability for someone to scan past it. There is actually <strong><em>a noted reduction in focus, and deep absorption of information</em></strong><sup>2</sup>, due to online reading habits. This not only affects the way we absorb information in books, but it can also impact the way we absorb source code.</p>
<h2 id="binding">Binding</h2>
<p>Since our job involves absorbing and using information quickly to make decisions, it is best if we can present relevant information quickly, and capitalize on the way people absorb language. This means, however, we need to look deeper into how we would improve the code in order to help retain engagement, and speed information seeking behaviors.</p>
<p>Linguistics offers insight into how people process context-heavy language. <strong><em>Binding</em></strong><sup>3</sup> is the way that people associate context from a larger communicated <strong><em>theme</em></strong><sup>4</sup> to support indefinite pronouns like: it, them, he, she, etc.</p>
<p>Example:</p>
<blockquote>
<p>Linda bought lunch at her favorite restaurant.</p>
</blockquote>
<p>The contextual object of this sentence is Linda. Every indefinite pronoun refers back to the original object, i.e. Linda. We can use this to our advantage, as long as we are aware of what the thematic object is in our variable name.</p>
<h2 id="identifying-a-thematic-object">Identifying a Thematic Object</h2>
<p>Let’s consider our sample source, again, and look for ideas which are repeated. Repeated ideas are typically indicative of a contextual theme, which can help to drive names.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">exceededWidgetsPerBox</span> <span class="o">=</span> <span class="nx">addedWidgets</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">maximumWidgetsPerBox</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">exceededMaxWidgetsPerBox</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Exceeded widget max</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I can see objects we can consider as thematic:</p>
<ul>
<li>widgets</li>
<li>box</li>
</ul>
<p>There are also descriptive concepts which can help us refine our discovery:</p>
<ul>
<li>box size (<code class="highlighter-rouge">maximumWidgetsPerBox</code>)</li>
<li>box is too full (<code class="highlighter-rouge">exceededWidgetsPerBox</code>)</li>
<li>widget count (<code class="highlighter-rouge">addedWidgets.length</code>)</li>
<li>adding widgets to a collection (<code class="highlighter-rouge">addedWidgets</code>)</li>
</ul>
<p>It seems as though widgets are a general set of any added widgets since we are counting the number which are there, and comparing the count to some other pre-set size. Also, the box seems to be distinct and definite, since it has a defined size, and carrying capacity.</p>
<p>Given our discovery, the thematic object is likely the box, and the widgets are, perhaps, part of a larger programmatic theme. Let’s use our identified theme to create a new context.</p>
<h2 id="contextualizing-with-functions-and-methods">Contextualizing With Functions and Methods</h2>
<p>Since we have landed on the box as the broader contextual idea, we can use this to create a new contextual marker. Much like in a sentence, any function or method will provide an intended context, or theme for the behavior.</p>
<p>By choosing a name for a method that captures our theme, we can reduce the length of our variable names, and use human language processing to our advantage to make our code clearer, and easier to scan.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">throwIfBoxTooFull</span><span class="p">(</span><span class="nx">addedWidgets</span><span class="p">,</span> <span class="nx">maximumWidgetCount</span><span class="p">){</span>
<span class="kd">const</span> <span class="nx">tooManyWidgets</span> <span class="o">=</span> <span class="nx">addedWidgets</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">maximumWidgetCount</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">tooManyWidgets</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Exceeded widget max</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>With this first pass, we have now lifted the idea of a box, and its size out of the local variable names, and created an implicit context which carries through the local block context. By knowing the <strong><em>focus</em></strong><sup>5</sup> is the box, our widget discussion is contained completely within that particular context.</p>
<h2 id="reading-code-aloud">Reading Code Aloud</h2>
<p>At this point we can revisit the discussion from Dr. Felienne Hermans, regarding <strong><em>code phonology</em></strong><sup>6</sup>, and we can start to unify the way this code might be read aloud. We have common markers for written language here, so it might be reasonable to interpret this code as follows:</p>
<blockquote>
<p>Throw an error if the box is too full. If there are too many widgets the error should be ‘Exceeded widget max’.</p>
</blockquote>
<p>This reading comes almost directly out of the definition of the function. There is, of course, an assumption of idiom around “throw” meaning “throw an error”. Otherwise, our phrasing actually makes the same thematic assumption, because of binding, that our code does.</p>
<p>The fact that we can map the expression of intent to our code in a meaningful way provides a clear path for the next developer to start unwinding the indent of the work which was done.</p>
<h2 id="whats-next">What’s Next</h2>
<p>Although this process may seem a little bulky, when you are looking at your code it is pretty common to have a theme jump out at you. The analytical breakdown above is simply to demonstrate how a thematic object can be selected from a section of your code. In practice, it’s often preferable to choose a best first guess for a name, and then iterate toward a better option as you discover more.</p>
<p>Our code snippet started with a rather long variable name in the mix. Though long variable names may be an indication of several things, when the subject is short and simple, it is often the case that the variable name, not the value, is actually doing too much work. Using the concept of binding, we can extract context and provide it implicitly through the name of a function or method.</p>
<p>It’s reasonable to assume this function is not isolated in a file, with only one reference to a box, or widgets. This same binding concept can be carried through to classes and namespaces, which we will look at in the future. It is important to note, the farther any named theme is from a variable, the less room you have to shift meaning.</p>
<p>With the concept of binding, we can offload the localized work of maintaining context and shift it to a higher-level abstraction. This kind linguistic abstraction provides direct insight into <strong><em>Dijkstra’s</em></strong><sup>7</sup> comment about abstraction:</p>
<blockquote>
<p>The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise.</p>
</blockquote>
<p><strong><em>References</em></strong></p>
<ol>
<li>“Naming Things Part the Second, or Simple Expressions” <a href="http://chrisstead.net/programming/human-centered-source/design/names/2021/02/22/naming-things-part-the-first-magic-primitives.html">http://chrisstead.net/programming/human-centered-source/design/names/2021/02/22/naming-things-part-the-first-magic-primitives.html</a></li>
<li>“Serious reading takes a hit from online scanning and skimming, researchers say” <a href="https://www.washingtonpost.com/local/serious-reading-takes-a-hit-from-online-scanning-and-skimming-researchers-say/2014/04/06/088028d2-b5d2-11e3-b899-20667de76985_story.html">https://www.washingtonpost.com/local/serious-reading-takes-a-hit-from-online-scanning-and-skimming-researchers-say/2014/04/06/088028d2-b5d2-11e3-b899-20667de76985_story.html</a></li>
<li>“Binding” <a href="https://en.wikipedia.org/wiki/Binding_(linguistics)">https://en.wikipedia.org/wiki/Binding_(linguistics)</a></li>
<li>“Topic and comment” <a href="https://en.wikipedia.org/wiki/Topic_and_comment">https://en.wikipedia.org/wiki/Topic_and_comment</a></li>
<li>“Focus” <a href="https://en.wikipedia.org/wiki/Focus_(linguistics)">https://en.wikipedia.org/wiki/Focus_(linguistics)</a></li>
<li>“Code Phonology” <a href="https://www.felienne.com/archives/5947">https://www.felienne.com/archives/5947</a></li>
<li>“Edsger Dijkstra” <a href="https://en.wikipedia.org/wiki/Edsger_W._Dijkstra">https://en.wikipedia.org/wiki/Edsger_W._Dijkstra</a></li>
</ol>Chris SteadThis is part three of a multi-part series on naming things. Part two will be useful1.Analyzing Source Code: Source Textemes2021-03-23T01:00:00-07:002021-03-23T01:00:00-07:00http://chrisstead.net/programming/source-code/linguistic-analysis/human-centered-source/2021/03/23/analyzing-source-code-textemes<p>I realized a few years ago that one of the most important aspects of writing software, to me, is to build it for people. For several years, I thought, given enough research, there was a technical solution out there that would help me to finally discover a way back to people.</p>
<p>As has been said many times before, <strong>there is no technical solution for people problems</strong>.</p>
<p>The more I learned about the <strong><em>sociotechnical</em></strong><sup>1</sup> inner workings of teams building software, the more I realized that no amount of technical knowledge would ever replace the value of better understanding people.</p>
<p>Jessica Kerr leans into Nora Bateson’s concept of <strong><em>symmathesy</em></strong><sup>2</sup>, “learning together”, as a description of the kind of work software developers do. This word is steeped in the notion of human systems, working together, communication, discovery, and much more. In order to be more effective <strong><em>symmathesistic</em></strong> team, we need tools.</p>
<p>There are numerous tools, and likely near-infinite approaches to developing an effective group working symmathesistically, however, it seemed most reasonable to lean into something I already understood: the <strong><em>metastructure</em></strong><sup>3</sup> of programming languages.</p>
<p>I ended up pulling a thread and landing squarely at the intersection of programming languages, communication, and linguistics. There are a number of reasons why any programming languages, as a core set of syntactic rules, would not be considered a language in isolation. On the other hand, when we consider the way programming languages are used by people, and the novel structures that emerge, it looks less like machine-generated commands, and more like the way people actually communicate.<!--more--></p>
<p>Of course one of the largest hurdles I had to overcome was the notion that any language would be necessarily spoken. Even considering <strong><em>code phonology</em></strong><sup>4</sup>, there is no uniform approach to truly reading code. This is, in my best estimation, due to the fact that reading code aloud is more an interpretive activity than a one-to-one conversion of written work to spoken words.</p>
<p>Consider this:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nx">records</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">record</span> <span class="o">=</span> <span class="nx">records</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`ID: </span><span class="p">${</span><span class="nx">record</span><span class="p">.</span><span class="nx">id</span><span class="p">}</span><span class="s2">, Name: </span><span class="p">${</span><span class="nx">record</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>If we just take the single line <code class="highlighter-rouge">if(records.length < 1) break;</code>, some may read it, literally, as “if records length is less than 1, break” while someone else might say “break when you run out of records.” Both of these interpretations are <strong><em>pragmatically</em></strong><sup>5</sup> valid. The latter may speak more accurately to code intent, even if it does not speak to the exact implementation.</p>
<p>This broad variability in verbally communicating information about the source code led me to a problem: How would I do any kind of meaningful investigation and analysis of code as a communication medium if the communication around it is so inconsistent?</p>
<p>I started looking for linguists who were analyzing texts for answers. Though I haven’t found, or developed a complete system for making sense of source code with respect to human communication, I have landed on a concept which makes for a solid founding notion.</p>
<h2 id="the-texteme-text-eem">The Texteme (text-eem)</h2>
<blockquote>
<p><strong><em>texteme</em></strong> (n)<sup>6</sup>: (linguistics) A unit of text, large enough to have intelligible meaning, that stands in relationship to other units of text.</p>
</blockquote>
<p>In linguistic analysis of text, a texteme is a selection of text that is large enough to be meaningful. It also “stands in relationship to other units of text”, meaning a texteme alone does not tell a full story. Instead, it is part of a larger body of work, in which a collection of textemes build a broader meaning.</p>
<p>If we consider any space-, dot-, equal-sign-, or colon-delimited piece of text in source code as a selection, we could, hypothetically, call it a texteme, since there is some sense of what any given selection might be in the technical sense of the language, and it’s mechanics. I, however, didn’t find that notion very compelling.</p>
<p>Consider the selection <code class="highlighter-rouge">records</code>. It is an identifier, which means it’s a variable, function name, or other user-defined construct. It is written in English, and the plural nature of the word tells us that, for whatever a record is, there are likely plural of them stored in records.</p>
<p>Is that a sufficient analysis within the scope of the source code? Perhaps, but only in the most technical, atomic sense. We are missing a lot of important information, especially if we consider the instance of <code class="highlighter-rouge">records</code> where we are doing this work: <code class="highlighter-rouge">records.shift()</code>.</p>
<p>Although records may stand alone, though arguably, only as a class of possible meanings and values, <code class="highlighter-rouge">shift</code> almost certainly does not, given the syntactic rules, and applicative rules of the language (in this case JavaScript). In fact, regardless of whether we can call <code class="highlighter-rouge">records</code> or <code class="highlighter-rouge">shift</code> textemes, they are definitely tokens.</p>
<h3 id="tokens">Tokens</h3>
<p>In language parsing, there is a concept of a <strong><em>token</em></strong>. A token is a selection of text which is generated when doing <strong><em>lexical analysis</em></strong><sup>7</sup> which can, possibly, be classified for the use of doing further analysis later.</p>
<p>To expand on tokens and how they help us with analysis of our source code, let’s consider <code class="highlighter-rouge">records</code>, and <code class="highlighter-rouge">shift</code>. In the case of our example source code, they are found together, as a larger expression <code class="highlighter-rouge">records.shift</code>. I will, from here on, refer to this kind of token combination as a <strong><em>compound token expression</em></strong>.</p>
<p>I’ll stop at this point. I have no intention of diving into the work of doing lexical analysis here, but it is an interesting diversion if you’re interested in writing a programming language, or doing natural language processing.</p>
<h3 id="a-source-code-definition-of-texteme">A Source Code Definition of Texteme</h3>
<p>Given the fact that not every token can be considered sufficiently intelligible on its own, this gives rise to the notion that in source code, a source texteme may either be a token, or a compound token expression. In fact, unless a token is a language key-word, it is most likely NOT a source texteme.</p>
<p>Instead, I offer this definition:</p>
<blockquote>
<p><strong><em>source texteme</em></strong> (n): (software linguistics) the smallest unit of text can still be unambiguously intelligible in relation to other source textemes.</p>
</blockquote>
<p>With this in mind, <code class="highlighter-rouge">records</code>, <code class="highlighter-rouge">records.shift</code>, and <code class="highlighter-rouge">records.shift()</code> are each distinct. The first two, in relation to the other text, are actually ambiguous, given they are incomplete. In fact, <code class="highlighter-rouge">records</code> is unlikely to ever be unambiguous in any context.</p>
<p>The compound token expression <code class="highlighter-rouge">records.shift</code> is only meaningful if the source author meant to refer to a function attached to records, and not call it. In a broader consideration, the proper source texteme would necessarily be <code class="highlighter-rouge">records.shift[TERM]</code> where <strong>TERM</strong> is a delimiting terminator in the source code. In a language like JavaScript, there is an explicit terminator available, <code class="highlighter-rouge">;</code>, but a new expression may be an acceptable termination of the previous compounding.</p>
<p>Since our sample code does NOT terminate after <code class="highlighter-rouge">shift</code>, assuming <code class="highlighter-rouge">records.shift[TERM]</code> would provide an incorrect analysis of the code. Instead, we know that the compound token expression is, in fact <code class="highlighter-rouge">records.shift()</code>, which is definitely unambiguous.</p>
<p>Given this analysis, <code class="highlighter-rouge">records.shift()</code> is the smallest unit of text which can still be unambiguously intelligible, and we have found a properly-sized source texteme for our line. In fact the line <code class="highlighter-rouge">records.shift()</code> comes from actually contains two distinct source textemes compounded with an equals operator:</p>
<ol>
<li><code class="highlighter-rouge">const record</code></li>
<li><code class="highlighter-rouge">records.shift()</code></li>
</ol>
<p>Each of these source textemes can be fully interpreted and understood alone. The first is clearly the creation of a constant identifier, the second is the call of a function attached to <code class="highlighter-rouge">records</code>. When compounded, we get <code class="highlighter-rouge">const record = records.shift()</code> which provides us a fully interpretable line.</p>
<h2 id="conclusion">Conclusion</h2>
<p>There is more work to be done with source textemes, but I believe this is a good first pass at identifying human meaning within source code. Moreover, it demonstrates that meaning and pure syntactical analysis are not the same, and that source documents can actually be analyzed and intentionally constructed to carry meaning beyond a simple instruction set for a computer.</p>
<p>By having a concept we can use to analyze and evaluate source code, perhaps we can find better ways to identify source which communicates well, and improve source which does not. The source texteme gives us a foundation to uncover and discuss richer topics regarding the natural asynchronous communication which arises in source code.</p>
<p><strong><em>References</em></strong></p>
<ol>
<li>“Sociotechnical Systems” <a href="https://en.wikipedia.org/wiki/Sociotechnical_system">https://en.wikipedia.org/wiki/Sociotechnical_system</a></li>
<li>“Symmathesy: A Word In Progress” <a href="https://norabateson.wordpress.com/2015/11/03/symmathesy-a-word-in-progress/">https://norabateson.wordpress.com/2015/11/03/symmathesy-a-word-in-progress/</a></li>
<li>“Metastructure” <a href="https://en.wiktionary.org/wiki/metastructure">https://en.wiktionary.org/wiki/metastructure</a></li>
<li>“Code Phonology” <a href="https://www.felienne.com/archives/5947">https://www.felienne.com/archives/5947</a></li>
<li>“Pragmatics” <a href="https://en.wikipedia.org/wiki/Pragmatics">https://en.wikipedia.org/wiki/Pragmatics</a></li>
<li>“Texteme” <a href="https://en.wiktionary.org/wiki/texteme">https://en.wiktionary.org/wiki/texteme</a></li>
<li>“Lexical Analysis” <a href="https://en.wikipedia.org/wiki/Lexical_analysis">https://en.wikipedia.org/wiki/Lexical_analysis</a></li>
</ol>Chris SteadI realized a few years ago that one of the most important aspects of writing software, to me, is to build it for people. For several years, I thought, given enough research, there was a technical solution out there that would help me to finally discover a way back to people.