Corrected a range of typos.

This commit is contained in:
Andy Ko 2017-04-18 08:45:50 -07:00
parent 7923f2e8a5
commit 475bd93319
2 changed files with 24 additions and 10 deletions

View file

@ -28,11 +28,9 @@
<h1>Program Comprehension</h1>
<div class="lead">Andrew J. Ko</div>
<p>Despite all of the different activities that we've talked about so far&mdash;communicating, coordinating, planning, designing, architecting&mdash;really, most of a software engineers time is spent reading code (<a href="#maalej">Maalej et al. 2014</a>). Sometimes this is their own code, which makes this reading easier. Most of the time, it is someone else's code, whether it's a teammate's, or part of a library or API you're using. We call this reading <strong>program comprehension</strong>.</p>
<p>Despite all of the activities that we've talked about so far&mdash;communicating, coordinating, planning, designing, architecting&mdash;really, most of a software engineers time is spent reading code (<a href="#maalej">Maalej et al. 2014</a>). Sometimes this is their own code, which makes this reading easier. Most of the time, it is someone else's code, whether it's a teammate's, or part of a library or API you're using. We call this reading <strong>program comprehension</strong>.</p>
<p>Being good at program comprehension is a critical skill. You need to be able to read a function and know what it will do with its inputs; you need to be able to read a class and understand its state and functionality; you also need to be able to comprehend a whole implementation, understanding its architecture. Without these skills, you can't test well, you can't debug well, and you can fix or enhance the systems you're building or maintaining. In fact, studies of software engineers' first year at their first job show that a significant majority of their time is spent trying to simply comprehend the architecture of the system they are building or maintaining and understanding the processes that are being followed to modify and enhance them (<a href="#dagenais">Dagenais et al. 2010</a>).</p>
<p>What's going on when developers comprehend code? Usually, developers are trying to answer questions about code that help them build larger models of how a program works. Because program comprehension is hard, they avoid it when they can, relying on explanations from other developers rather than trying to build precise models of how a program works on their own (<a href="#roehm">Roehm et al. 2012</a>). When they do try to comprehend code, developers are usually trying to answer questions. Several studies have many general questions that developers must be able to answer in order to understand programs (<a href="#sillito">Sillito et al. 2006</a>, <a href="#latoza">LaToza & Myers 2010</a>). Here are over forty common questions that developers ask:</p>
@ -111,13 +109,13 @@
</tr>
</table>
<p>If you think about the massive diversity in this list, you can see why program comprehension requires expertise. You not only need to understand programming languages quite well, but you also need to have strategies for answering all of the questions above (and more) quickly, effectively, and accurately.</p>
<p>If you think about the diversity of questions in this list, you can see why program comprehension requires expertise. You not only need to understand programming languages quite well, but you also need to have strategies for answering all of the questions above (and more) quickly, effectively, and accurately.</p>
<p>So how do developers go about answering these questions? Studies comparing experts and novices show that experts use prior knowledge that they have about architecture, design patterns, and the problem domain a program is built for to know what questions to ask and how to answer them, whereas novices use surface features of code, which leads them to spend considerable time reading code that is irrelevant to a question ((<a href="#vonmay">von Mayrhauser & Vans 1994</a>), <a href="latoza2">LaToza et al. 2007</a>). Fundamentally, reading and comprehending source code is fundamentally different from those of reading and comprehending natural language (<a href="#binkley">Binkley et al. 2013</a>); what experts are doing is ultimately reasoning about <strong>dependencies</strong> between code (<a href="#weiser">Weiser 1981</a>). Dependencies include things like <strong>data dependencies</strong> (where a variable is used to compute something, what modifies a data structure, how data flows through a program, etc.) and <strong>control dependencies</strong> (which components call which functions, which events can trigger a function to be called, how a function is reached, etc.). All of the questions above fundamentally get at different types of data and control dependencies. In fact, theories of how developers navigate code by following these dependencies are highly predictive of what information a developer will seek next (<a href="#fleming">Fleming et al. 2013</a>), suggesting that expert behavior is highly routine.</p>
<p>So how do developers go about answering these questions? Studies comparing experts and novices show that experts use prior knowledge that they have about architecture, design patterns, and the problem domain a program is built for to know what questions to ask and how to answer them, whereas novices use surface features of code, which leads them to spend considerable time reading code that is irrelevant to a question (<a href="#vonmay">von Mayrhauser & Vans 1994</a>, <a href="latoza2">LaToza et al. 2007</a>). Reading and comprehending source code is fundamentally different from those of reading and comprehending natural language (<a href="#binkley">Binkley et al. 2013</a>); what experts are doing is ultimately reasoning about <strong>dependencies</strong> between code (<a href="#weiser">Weiser 1981</a>). Dependencies include things like <strong>data dependencies</strong> (where a variable is used to compute something, what modifies a data structure, how data flows through a program, etc.) and <strong>control dependencies</strong> (which components call which functions, which events can trigger a function to be called, how a function is reached, etc.). All of the questions above fundamentally get at different types of data and control dependencies. In fact, theories of how developers navigate code by following these dependencies are highly predictive of what information a developer will seek next (<a href="#fleming">Fleming et al. 2013</a>), suggesting that expert behavior is highly procedural.</p>
<p>While much of program comprehension is skill, some of it is determined by design. For example, some programming languages result in programs that are more comprehensible. One framework called the <em>Cognitive Dimensions of Notations</em> (<a href="#green">Green 1989</a>) lays out some of the tradeoffs in programming language design that result in these differences in comprehensibility. For example, one of the dimensions in the framework is <strong>consistency</strong>, which refers to how much of a notation can be guessed based on an initial understanding of a language. JavaScript is a low-consistency language because of operators like <code>==</code>, which behave differently depending on what the type of the left and right operands are. Knowing the behavior for Booleans doesn't tell you the behavior for a Boolean being compared to an integer. In contrast, Java is a high consistency language: <code>==</code> is only ever valid when both operands are of the same type.</p>
<p>These differences in notation have real impact. Encapsulation through data structures leads to better comprehension that monolithic or purely functional languages (<a href="#woodfield">Woodfield et al. 1981</a>, <a href="#bhattacharya">Bhattacharya & Neamtiu</a>). Declarative programming paradigms (like the JavaScript <a href="https://facebook.github.io/react/">React</a>) have greater comprehensibility than imperative languages (<a href="#salvaneschi">Salvaneschi et al. 2014</a>). In general, languages that are statically typed result in fewer defects (<a href="#ray">Ray et la. 2014</a>), better comprehensibility because of the ability to construct better documentation (<a href="#endrikat">Endrikat et al. 2014</a>), and result in easier debugging (<a href="#hanenberg">Hanenberg et al. 2013</a>). In fact, studies of more dynamic languages like JavaScript and Smalltalk (<a href="#callau">Calla&uacute et al. 2013</a>) show that the dynamic features of these languages aren't really used all that much anywhere. It appears then that the more you tell a compiler about what your code means, the more it helps the other developers know what it means too.</p>
<p>These differences in notation have real impact. Encapsulation through data structures leads to better comprehension that monolithic or purely functional languages (<a href="#woodfield">Woodfield et al. 1981</a>, <a href="#bhattacharya">Bhattacharya & Neamtiu</a>). Declarative programming paradigms (like the JavaScript view framework <a href="https://facebook.github.io/react/">React</a>) have greater comprehensibility than imperative languages (<a href="#salvaneschi">Salvaneschi et al. 2014</a>). In general, languages that are statically typed result in fewer defects (<a href="#ray">Ray et la. 2014</a>), better comprehensibility because of the ability to construct better documentation (<a href="#endrikat">Endrikat et al. 2014</a>), and result in easier debugging (<a href="#hanenberg">Hanenberg et al. 2013</a>). In fact, studies of more dynamic languages like JavaScript and Smalltalk (<a href="#callau">Calla&uacute et al. 2013</a>) show that the dynamic features of these languages aren't really used all that much anyway. All of this evidence suggests that that the more you tell a compiler about what your code means (by declaring types, writing functional specifications, etc.), the more it helps the other developers know what it means too.</p>
<p>Code editors, development environments, and program comprehension tools can also be helpful. Early evidence showed that simple features like syntax highlighting and careful typographic choices can improve the speed of program comprehension (<a href="#baecker">Baecker 1988</a>). I have also worked on several tools to support program comprehension, including the Whyline, which automates many of the more challenging aspects of navigating dependencies in code, and visualizes them (<a href="#ko">Ko & Myers 2009</a>):</p>

View file

@ -36,7 +36,7 @@
<img src="images/spiral.png" class="img-responsive" />
<p>Around the same time, two influential books were published. Fred Brooks wrote <strong>The Mythical Man Month</strong> (<a href="#brooks">Brooks 1995</a>), a book about software project management, full of provocative ideas that would be tested over the next three decades, including the idea that adding more people to a project would not necessarily increase productivity. Tom DeMarco and Timothy Lister wrote another famous book, <strong>Peopleware: Productive Projects and Teams</strong> (<a href="#demarco">DeMarco 1987</a>), arguing that the major challenges in software engineering are human, not technical. Both of these works still represent some of the most widely-read statements of the problem of managing software development processes.</p>
<p>Around the same time, two influential books were published. Fred Brooks wrote <strong>The Mythical Man Month</strong> (<a href="#brooks">Brooks 1995</a>), a book about software project management, full of provocative ideas that would be tested over the next three decades, including the idea that adding more people to a project would not necessarily increase productivity. Tom DeMarco and Timothy Lister wrote another famous book, <strong>Peopleware: Productive Projects and Teams</strong> (<a href="#demarco">DeMarco 1987</a>), arguing that the major challenges in software engineering are human, not technical. Both of these works still represent some of the most widely-read statements of the problem of managing software development.</p>
<p>These early ideas in software project management led to a wide variety of other discoveries about process. For example, organizations of all sizes can improve their process if they are very aware of what the people in the organization know, what it's capable of learning, and if it builds robust processes to actually continually improve process (<a href="dyba2">Dyb&#551; 2002</a>, <a href="#dyba">Dyb&#551; 2003</a>). This might mean monitoring the pace of work, incentivizing engineers to reflect on inefficiencies in process, and teaching engineers how to be comfortable with process change.</p>
@ -48,13 +48,28 @@
<p>Because of the importance of awareness and communication, the <strong>distance</strong> between teammates is also a critical factor. This is most visible in companies that hire remote developers, building distributed teams. The primary motivation for doing this is to reduce costs or gain access to engineering talent that is distant from a team's geographical center, but over time, companies have found that doing so necessitates significant investments in travel and socialization to ensure quality, minimizing geographical, temporal and cultural separation (<a href="smite">Smite 2010</a>). Researchers have found that there appear to be fundamental tradeoffs between productivity, quality, and/or profits in these settings (<a href="#ramasubbu">Ramasubbu et al. 2011</a>). For example, more distance appears to lead to slower communication (<a href="#wagstrom">Wagstrom & Datta 2014</a>). Despite these tradeoffs, most rigorous studies of the cost of distributed development have found that when companies work hard to minimize temporal and cultural separation, the actual impact on defects was small (<a href="#kocaguneli">Kocaguneli et al. 2013</a>). Some researchers have begun to explore even more extreme models of distributed development, hiring contract developers to complete microtasks over a few days without hiring them as employees; early studies suggest that these models have the worst of outcomes, with greater costs, poor scalability, and more significant quality issues (<a href="#stol">Stol & Fitzgerald 2014</a>).</p>
<p>While all of these research was being conducted, industry explored its own ideas about process, devising frameworks that addressed issues of distance, pace, ownership, awareness, and process improvement. Extreme Programming (<a href="beck">Beck 1999</a>) was one of these frameworks and it was full of ideas: be iterative, do small releases, keep design simple, write unit tests, refactor to iterate, use pair programming, integrate continuously, everyone owns everything, use an open workspace, work sane hours. Beck described in his original proposal that these ideas were best for "outsourced or in-house development of small- to medium-sized systems where requirements are vague and likely to change", but as industry often does, it began hyping it as a universal solution to software project management woes and adopted all kinds of combinations of these ideas, adapting them to their existing processes. In reality, the value of XP appears to depend on highly project-specific factors (<a href="muller">M&uuml;ller & Padberk 2013</a>), while the core ideas that industry has adopted are valuing feedback, communication, simplicity, and respect for individuals and the team (<a href="sharp">Sharp & Robinson 2004</a>).</p>
<p>While all of these research was being conducted, industry explored its own ideas about process, devising frameworks that addressed issues of distance, pace, ownership, awareness, and process improvement. Extreme Programming (<a href="beck">Beck 1999</a>) was one of these frameworks and it was full of ideas:</p>
<ul>
<li>Be iterative</li>
<li>Do small releases</li>
<li>Keep design simple</li>
<li>Write unit tests</li>
<li>Refactor to iterate</li>
<li>Use pair programming</li>
<li>Integrate continuously</li>
<li>Everyone owns everything</li>
<li>Use an open workspace</li>
<li>Work sane hours</li>
</ul>
<p>Note that none of these had any empirical evidence to back them. Moreover, Beck described in his original proposal that these ideas were best for "<em>outsourced or in-house development of small- to medium-sized systems where requirements are vague and likely to change</em>", but as industry often does, it began hyping it as a universal solution to software project management woes and adopted all kinds of combinations of these ideas, adapting them to their existing processes. In reality, the value of XP appears to depend on highly project-specific factors (<a href="muller">M&uuml;ller & Padberk 2013</a>), while the core ideas that industry has adopted are valuing feedback, communication, simplicity, and respect for individuals and the team (<a href="sharp">Sharp & Robinson 2004</a>). Researchers continue to investigate the merits of the list above; for example, numerous studies have investigated the effects of pair programming on defects, finding small but measurable benefits (<a href="#dibella">di Bella et al. 2012</a>)</p>
<p>At the same time, Beck began also espousing the idea of <a href="http://agilemanifesto.org/" target="_blank">"Agile" methods</a>, which celebrated many of the values underlying Extreme Programming, such as focusing on individuals, keeping things simple, collaborating with customers, and being iterative. This idea of begin agile was even more popular and spread widely in industry and research, even though many of the same ideas appeared much earlier in Boehm's work on the Spiral model. Researchers found that Agile methods can increase developer enthusiasm (<a href="syed">Syed-Abdulla et al. 2006</a>), that agile teams need different roles such as Mentor, Co-ordinator, Translator, Champion, Promoter, and Terminator (<a href="#hoda">Hoda et al. 2010</a>), and that teams are combing agile methods with all kinds of process ideas from other project management frameworks such as <a href="https://en.wikipedia.org/wiki/Scrum_(software_development)">Scrum</a> (meet daily to plan work, plan two-week sprints, maintain a backlog of work) and Kanban (visualize the workflow, limit work-in-progress, manage flow, make policies explicit, and implement feedback loops) (<a href="#al-baik">Al-Baik & Miller 2015</a>). I don't define any of these ideas here because there aren't standard definitions to share.</p>
<p>Ultimately, all of this energy around process ideas in industry is exciting, but disorganized. None of these efforts really get to the core of what makes software projects difficult to manage. One effort in research to get to this core by contributing new theories that explain these difficulties. The first is Herbsleb's <strong>Socio-Technical Theory of Coordination (STTC)</strong>. The idea of the theory is quite simple: dependencies in engineering decisions (e.g., this function calls this other function, this data type stores this other data type) define the social constraints that the organization must solve in a variety of ways to build and maintain software (<a href="#herbslebmockus">Herbsleb & Mockus 2003</a>, <a href="#herbsleb">Herbsleb 2016</a>). The better the organization builds processes and awareness tools to ensure that the people who own those engineering dependencies are communicating and aware of each others' work, the fewer defects that will occur. Herbsleb referred this alignment as <em>sociotechnical congruence</em>, and conducted a number of studies demonstrating its predictive and explanatory power.</p>
<p>Ultimately, all of this energy around process ideas in industry is exciting, but disorganized. None of these efforts really get to the core of what makes software projects difficult to manage. One effort in research to get to this core by contributing new theories that explain these difficulties. The first is Herbsleb's <strong>Socio-Technical Theory of Coordination (STTC)</strong>. The idea of the theory is quite simple: <em>technical dependencies</em> in engineering decisions (e.g., this function calls this other function, this data type stores this other data type) define the <em>social constraints</em> that the organization must solve in a variety of ways to build and maintain software (<a href="#herbslebmockus">Herbsleb & Mockus 2003</a>, <a href="#herbsleb">Herbsleb 2016</a>). The better the organization builds processes and awareness tools to ensure that the people who own those engineering dependencies are communicating and aware of each others' work, the fewer defects that will occur. Herbsleb referred this alignment as <em>sociotechnical congruence</em>, and conducted a number of studies demonstrating its predictive and explanatory power.</p>
<p>In my recent work (</a href="#ko2">Ko 2017</a>), I extend this idea to congruence with beliefs about <em>product</em> value, claiming that successful software products require the constant, collective communication and agreement of a coherent proposition of a product's value across UX, design, engineering, product, marketing, sales, support, and even customers. A team needs to achieve Herbsleb's sociotechnical congruence to have a successful product, but that alone is not enough: the rest of the organization has to have a consistent understanding of what is being built and why, even as that understanding evolves over time.</p>
<p>In my recent work (<a href="#ko2">Ko 2017</a>), I extend this idea to congruence with beliefs about <em>product</em> value, claiming that successful software products require the constant, collective communication and agreement of a coherent proposition of a product's value across UX, design, engineering, product, marketing, sales, support, and even customers. A team needs to achieve Herbsleb's sociotechnical congruence to have a successful product, but that alone is not enough: the rest of the organization has to have a consistent understanding of what is being built and why, even as that understanding evolves over time.</p>
<center class="lead"><a href="comprehension.html">Next chapter: Comprehension</a></center>
@ -67,6 +82,7 @@
<p id="bird">Christian Bird, Nachiappan Nagappan, Brendan Murphy, Harald Gall, and Premkumar Devanbu. 2011. <a href="http://dx.doi.org/10.1145/2025113.2025119" target="_blank">Don't touch my code! Examining the effects of ownership on software quality</a>. In Proceedings of the 19th ACM SIGSOFT symposium and the 13th European conference on Foundations of software engineering (ESEC/FSE '11). ACM, New York, NY, USA, 4-14.</a>
<p id="boehm">Boehm, B. W. (1988). <a href="http://ieeexplore.ieee.org/abstract/document/59/" target="_blank">A spiral model of software development and enhancement</a>. Computer, 21(5), 61-72.</p>
<p id="brooks">Brooks, F.P. (1995). <a href="https://books.google.com/books?id=Yq35BY5Fk3gC" target="_blank">The Mythical Man Month</a>.</p>
<p id="dibella">di Bella, E., Fronza, I., Phaphoom, N., Sillitti, A., Succi, G., & Vlasenko, J. (2013). <a href="https://doi.org/10.1109/TSE.2012.68">Pair Programming and Software Defects--A Large, Industrial Case Study</a>. IEEE Transactions on Software Engineering, 39(7), 930-953.</p>
<p id="demarco">DeMarco, T. and Lister, T. (1987). <a href="https://books.google.com/books?id=TVQUAAAAQBAJ" target="_blank">Peopleware: Productive Projects and Teams</a>.</p>
<p id="dyba">Tore Dyb&#551;. 2003. <a href="http://dx.doi.org/10.1145/940071.940092" target="_blank">Factors of software process improvement success in small and large organizations: an empirical study in the scandinavian context</a>. In Proceedings of the 9th European software engineering conference held jointly with 11th ACM SIGSOFT international symposium on Foundations of software engineering (ESEC/FSE-11). ACM, New York, NY, USA, 148-157.</p>
<p id="dyba2">Dyb&#551;, T. (2002). <a href="https://link.springer.com/article/10.1023/A:1020535725648" target="_blank">Enabling software process improvement: an investigation of the importance of organizational issues</a>. Empirical Software Engineering, 7(4), 387-390.</p>