PageSourceSearch

https://tobiasduerschmid.github.io/SEBook/

html tobiasduerschmid.github.io collected 2026-10-03 10:05:21 UTC 153,298 bytes, 4,425 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3
4
5
6
7<head>
8  <meta charset="utf-8">
9  <meta name="viewport" content="width=device-width, initial-scale=1">
10
11  
12
13  <!-- Early display-preference initialization to prevent blinking -->
14  
14<script>
15    (function () {
16      var nameEQ = "show-highlights=";
17      var darkEQ = "dark-mode=";
18      var confettiEQ = "more-confetti=";
19      var blogCitationsEQ = "blog-show-citations=";
20      var ca = document.cookie.split(';');
21      var show = true;
22      var dark = false;
23      var moreConfetti = true;
24      var blogCitations = true;
25      for (var i = 0; i < ca.length; i++) {
26        var c = ca[i];
27        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
28        if (c.indexOf(nameEQ) == 0) {
29          show = c.substring(nameEQ.length, c.length) === 'true';
30        }
31        if (c.indexOf(darkEQ) == 0) {
32          dark = c.substring(darkEQ.length, c.length) === 'true';
33        }
34        if (c.indexOf(confettiEQ) == 0) {
35          moreConfetti = c.substring(confettiEQ.length, c.length) !== 'false';
36        }
37        if (c.indexOf(blogCitationsEQ) == 0) {
38          blogCitations = c.substring(blogCitationsEQ.length) !== 'false';
39        }
40      }
41      if (!show) {
42        document.documentElement.classList.add('highlights-disabled');
43      }
44      if (dark) {
45        document.documentElement.classList.add('dark-mode');
46      }
47      if (moreConfetti) {
48        document.documentElement.classList.add('more-confetti-enabled');
49      }
50      if (!blogCitations) {
51        document.documentElement.classList.add('blog-citations-disabled');
52      }
53      try {
54        if (localStorage.getItem('abbr-underlines') === 'false') {
55          document.documentElement.classList.add('abbr-underlines-disabled');
56        }
57      } catch (e) {}
58    })();
59  </script>
59
60
61  <!-- Print always uses the light palette, regardless of the saved site
62       theme. We remove only the runtime class while the browser is preparing
63       print/print-preview, then restore it after printing so the user's
64       preference and cookie stay unchanged. -->
65  
65<script>
66    (function () {
67      var root = document.documentElement;
68      var wasDarkBeforePrint = false;
69      var printModeActive = false;
70
71      function classText() {
72        return root.className || '';
73      }
74
75      function hasClass(name) {
76        return (' ' + classText() + ' ').indexOf(' ' + name + ' ') !== -1;
77      }
78
79      function addClass(name) {
80        if (root.classList && typeof root.classList.add === 'function') {
81          root.classList.add(name);
82          return;
83        }
84        if (!hasClass(name)) {
85          root.className = classText() ? classText() + ' ' + name : name;
86        }
87      }
88
89      function removeClass(name) {
90        if (root.classList && typeof root.classList.remove === 'function') {
91          root.classList.remove(name);
92          return;
93        }
94        root.className = (' ' + classText() + ' ').replace(' ' + name + ' ', ' ').trim();
95      }
96
97      function enterPrintMode() {
98        if (printModeActive) return;
99        printModeActive = true;
100        wasDarkBeforePrint = hasClass('dark-mode');
101        removeClass('dark-mode');
102        addClass('print-light-mode');
103      }
104
105      function exitPrintMode() {
106        if (!printModeActive) return;
107        printModeActive = false;
108        removeClass('print-light-mode');
109        if (wasDarkBeforePrint) {
110          addClass('dark-mode');
111        }
112        wasDarkBeforePrint = false;
113      }
114
115      window.addEventListener('beforeprint', enterPrintMode);
116      window.addEventListener('afterprint', exitPrintMode);
117
118      if (window.matchMedia) {
119        var printMedia = window.matchMedia('print');
120        var syncPrintMedia = function () {
121          if (printMedia.matches) enterPrintMode();
122          else exitPrintMode();
123        };
124        if (printMedia.addEventListener) printMedia.addEventListener('change', syncPrintMedia);
125        else if (printMedia.addListener) printMedia.addListener(syncPrintMedia);
126        syncPrintMedia();
127      }
128    })();
129  </script>
129
130
131  <!-- Reduced-motion detection: runs BEFORE any other JS on the page so
132       lab scripts that check `window.__prefersReducedMotion` on init see
133       the final value, and so the `html.prm-reduce` class is applied in
134       the same paint as first render (no flash of motion).
135
136       Three signals, in precedence order:
137         1. `?reduce-motion=1|0` URL param   (highest — explicit user intent).
138            `=1` turns on and stores in localStorage; `=0` turns off and
139            clears the store.
140         2. `localStorage.prefersReducedMotion === '1'`  (persistent
141            override — survives tab close and browser restart until the
142            user explicitly visits with `?reduce-motion=0` or clears site
143            data).
144         3. `window.matchMedia('(prefers-reduced-motion: reduce)').matches`
145            — the OS-level accessibility pref, the canonical signal.
146
147       Uses localStorage so the preference sticks across tabs and
148       restarts. To turn it off, append `?reduce-motion=0` once — that
149       removes the localStorage entry, and subsequent visits fall back
150       to the OS preference. -->
151  
151<script>
152    (function () {
153      // One-time migration: if an earlier sessionStorage-based version of
154      // this script left a value there, promote it to localStorage so we
155      // don't accidentally forget the user's choice when they close the
156      // tab. (Harmless if the key doesn't exist.)
157      try {
158        if (sessionStorage.getItem('prefersReducedMotion') === '1'
159            && localStorage.getItem('prefersReducedMotion') !== '1') {
160          localStorage.setItem('prefersReducedMotion', '1');
161        }
162        sessionStorage.removeItem('prefersReducedMotion');
163      } catch (e) {}
164
165      var STORE_KEY = 'prefersReducedMotion';
166      function readStore() {
167        try { return localStorage.getItem(STORE_KEY) === '1'; } catch (e) { return false; }
168      }
169      function writeStore(on) {
170        try {
171          if (on) localStorage.setItem(STORE_KEY, '1');
172          else localStorage.removeItem(STORE_KEY);
173        } catch (e) {}
174      }
175      var forced = null;  // null = no URL param, true/false = explicit
176      try {
177        var p = new URLSearchParams(window.location.search).get('reduce-motion');
178        if (p != null) {
179          forced = !(p === '0' || p.toLowerCase() === 'false');
180          writeStore(forced);   // persist the explicit choice
181        }
182      } catch (e) {}
183      var stored = readStore();
184      var mq = (window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null);
185      function active() {
186        if (forced !== null) return forced;   // current-page URL wins
187        if (stored) return true;              // persistent override
188        return !!(mq && mq.matches);          // OS preference
189      }
190      function sync() {
191        if (document.documentElement) {
192          document.documentElement.classList.toggle('prm-reduce', active());
193        }
194      }
195      sync();
196      if (mq) {
197        if (mq.addEventListener) mq.addEventListener('change', sync);
198        else if (mq.addListener) mq.addListener(sync);
199      }
200      // Single, site-wide helper — lab scripts call this instead of
201      // window.matchMedia directly so the URL override, stored override
202      // and OS pref are honoured uniformly.
203      window.__prefersReducedMotion = active;
204    })();
205  </script>
205
206
207  
208    
209    
210    
211    <title>SE Book — Table of Contents | SE Book</title>
212    <meta property="og:title" content="SE Book — Table of Contents" />
213    <meta property="og:site_name" content="SE Book" />
214    <meta name="description" content="A collection of topics for students in software engineering courses" />
215    <meta property="og:description" content="A collection of topics for students in software engineering courses" />
216    <meta property="twitter:title" content="SE Book — Table of Contents" />
217    <meta name="twitter:card" content="summary" />
218    <meta property="og:type" content="website" />
219    <meta property="og:locale" content="en" />
220    <meta property="og:url" content="https://tobiasduerschmid.github.io/SEBook/" />
221    
222    <meta name="google-site-verification" content="PsUhrtR2-1XWZ0diQcCbt0egBzKjidLDPTl5WB3s-2E" />
223    
224  
225  
226<meta name="tdm-reservation" content="1">
227<meta name="robots" content="noai, noimageai, noarchive">
228<meta name="dcterms.rights" content="Tobias Dürschmid expressly reserves the use of this site&#39;s content for text and data mining, including training or fine-tuning AI models, pursuant to Article 4(3) of Directive (EU) 2019/790. Any such use requires prior written permission.">
229
230
231  
232
233  <!-- Bootstrap Core CSS -->
234  <!-- themes (*preferred):
235    cerulean, cosmo*, cyborg, darkly*, flatly*, journal, lumen, paper, readable, sandstone*, simplex*, slate*, spacelab, superhero*, united*, yeti* -->
236  <!--<link rel="stylesheet" href="https://bootswatch.com/3/yeti/bootstrap.min.css">-->
237  <link rel="stylesheet" href="/css/bootstrap.ucla.css">
238
239  <!-- Site-wide design tokens (CSS custom properties). Loads early so the
240       variables are available to every later stylesheet and inline style. -->
241  <link rel="stylesheet" href="/css/design-tokens.css?v=20260927-sebook-landing-hero">
242
243  <!-- Custom CSS -->
244  <link rel="stylesheet" href="https://blueimp.github.io/Gallery/css/blueimp-gallery.min.css"
245        integrity="sha384-0OXfFxR9IwMRUzwuBmZ4sHQYSUwbgaS+h3NnDzt81CW4FEkP8o3pc3wvTZHPclLZ"
246        crossorigin="anonymous">
247  <link rel="stylesheet" href="/css/bootstrap-image-gallery.min.css">
248  <link rel="stylesheet" href="/css/scrolling-nav.css">
249  <link rel="stylesheet" href="/css/portfolio.css?v=20260927-sebook-landing-hero">
250  <link rel="stylesheet" href="/css/hoverex-all.css">
251  <link rel="stylesheet" href="/css/unslider.css">
252  <link rel="stylesheet" href="/css/unslider-dots.css">
253  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css"
254        integrity="sha384-nRgPTkuX86pH8yjPJUAFuASXQSSl2/bBUiNV47vSYpKFxHJhbcrGnmlYpYJMeD7a"
255        crossorigin="anonymous">
256  <link rel="stylesheet" href="/css/main.css?v=20260927-sebook-landing-hero">
257  <link rel="stylesheet" href="/css/sebook-theme.css?v=20260927-sebook-landing-hero">
258  <link rel="stylesheet" href="/css/site-components.css?v=20260927-sebook-landing-hero">
259  <link rel="stylesheet" href="/css/info-pages.css?v=20260927-sebook-landing-hero">
260  <link rel="stylesheet" href="/css/sebook-content-pages.css?v=20260927-sebook-landing-hero">
261  <link rel="stylesheet" href="/css/sebook-bookmarks.css?v=20260927-sebook-landing-hero">
262  <link rel="stylesheet" href="/css/regex-pages.css?v=20260927-sebook-landing-hero">
263  <link rel="stylesheet" href="/css/sebook-quiz.css?v=20260927-sebook-landing-hero">
264  <link rel="stylesheet" href="/css/sebook-flashcards.css?v=20260927-sebook-landing-hero">
265  <link rel="stylesheet" href="/css/spec-card.css?v=20260927-sebook-landing-hero">
266  <link rel="stylesheet" href="/css/tutorial-uml-editor.css?v=20260927-sebook-landing-hero">
267  
268  
269  <link rel="stylesheet" href="/css/uml-diagram.css">
270  
271  <link rel="stylesheet" href="/css/print-light.css?v=20260927-sebook-landing-hero">
272
273  <link rel="canonical" href="https://tobiasduerschmid.github.io/SEBook/">
274
275  
275<script src="/js/confetti.js"></script>
275
276  
276<script src="/js/accessibility-fixes.js" defer></script>
276
277
278  
279  
279<script src="/js/se-gym.js"></script>
279
280  
281
282  
283  
283<script src="/js/se-bookmarks.js"></script>
283
284  
285
286  <!-- MathJax Configuration for LaTeX Math Rendering -->
287  
287<script>
288    MathJax = {
289      tex: {
290        inlineMath: [['$', '$'], ['\\(', '\\)']],
291        displayMath: [['$$', '$$'], ['\\[', '\\]']],
292        processEscapes: true
293      },
294      options: {
295        skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
296      }
297    };
298  </script>
298
299  
299<script id="MathJax-script" async
300          src="https://cdn.jsdelivr.net/npm/[email protected]/es5/tex-chtml.js"
301          integrity="sha384-AHAnt9ZhGeHIrydA1Kp1L7FN+2UosbF7RQg6C+9Is/a7kDpQ1684C2iH2VWil6r4"
302          crossorigin="anonymous"></script>
302
303
304</head>
305
306
307<body id="page-top" class="sebook-layout" data-spy="scroll" data-target=".navbar-fixed-top" data-offset="100">
308  <a href="#main-content" class="skip-link">Skip to main content</a>
309
310  <div class="post-content">
311
312    <nav class="navbar top-nav-collapse navbar-inverse navbar-fixed-top" id="navnav" aria-label="Main navigation">
313      <div class="container-fluid">
314        <div class="navbar-header page-scroll">
315          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"
316            aria-label="Toggle navigation menu" aria-expanded="false" aria-controls="primary-nav-collapse">
317            <span class="sr-only">Toggle navigation</span>
318            <span class="icon-bar" aria-hidden="true"></span>
319            <span class="icon-bar" aria-hidden="true"></span>
320            <span class="icon-bar" aria-hidden="true"></span>
321          </button>
322          <a class="navbar-brand page-scroll" href="/SEBook/">SE Book</a><a
323            class="navbar-brand page-scroll" href="/">Tobias Dürschmid</a>
324
325        </div>
326        <!-- Collect the nav links, forms, and other content for toggling -->
327        <div class="collapse navbar-collapse navbar-ex1-collapse" id="primary-nav-collapse">
328          <ul class="nav navbar-nav navbar-right">
329            <!-- Extract H1 headings from content -->
330              
331                     
332              <li><a class="page-scroll"
333                href="#table-of-contents">Table of Contents</a></li>
334              
335              
336              
337          </ul>
338        </div><!--/.nav-collapse -->
339      </div>
340    </nav>
341
342
343    <div id="sebook-content-wrapper" class="has-hero">
344      <!-- Full-width landing banner (front matter `hero:`); replaces the page header -->
345      <section class="sebook-hero" aria-labelledby="sebook-hero-title">
346  <div class="sebook-hero-inner">
347    <div class="sebook-hero-copy">
348      <h1 id="sebook-hero-title" class="sebook-hero-title">The SE Book</h1>
349      <p class="sebook-hero-tagline">From coder to <span class="sebook-hero-accent">engineer</span>.</p>
350      <p class="sebook-hero-lede">
351        Git, testing, design patterns, architecture, and teamwork: everything
352        software engineering adds to the code, with hands-on tutorials that
353        run right in your browser.
354      </p>
355      <div class="sebook-hero-actions">
356        <a class="sebook-hero-button sebook-hero-button--primary" href="#table-of-contents">Browse the chapters</a>
357        <a class="sebook-hero-button sebook-hero-button--secondary" href="/SEBook/tutorials">Try a tutorial</a>
358      </div>
359      <p class="sebook-hero-courses">
360        The SE Book brings together material for students in
361        <a href="/SEBook/CS35L_bookmarks.html">CS&nbsp;35L</a>,
362        <a href="/SEBook/CS130_bookmarks.html">CS&nbsp;130</a>, and
363        <a href="/SEBook/CS131_bookmarks.html">CS&nbsp;131</a>.
364      </p>
365    </div>
366    <div class="sebook-hero-media">
367      <div class="sebook-teaser">
368  <video
369    class="sebook-teaser-video"
370    controls
371    playsinline
372    preload="none"
373    width="1920"
374    height="1080"
375    poster="/assets/video/sebook-teaser-poster.jpg"
376    aria-label="The SE Book in 20 seconds">
377    <source src="/assets/video/sebook-teaser.mp4" type="video/mp4">
378    <track kind="captions" src="/assets/video/sebook-teaser.vtt" srclang="en" label="English">
379    <p>Your browser can't play this video. <a href="/assets/video/sebook-teaser.mp4">Download the teaser video</a> or read its transcript.</p>
380  </video>
381
382  <details class="sebook-teaser-extras">
383    <summary>Audio description and transcript</summary>
384    <p class="sebook-teaser-label">Audio-described version: a narrator reads the on-screen text over the music.</p>
385    <video
386      class="sebook-teaser-video"
387      controls
388      playsinline
389      preload="none"
390      width="1920"
391      height="1080"
392      poster="/assets/video/sebook-teaser-poster.jpg"
393      aria-label="The SE Book in 20 seconds, with audio description">
394      <source src="/assets/video/sebook-teaser-described.mp4" type="video/mp4">
395      <track kind="captions" src="/assets/video/sebook-teaser-described.vtt" srclang="en" label="English">
396      <p>Your browser can't play this video. <a href="/assets/video/sebook-teaser-described.mp4">Download the audio-described teaser video</a>.</p>
397    </video>
398
399    <p class="sebook-teaser-label">Transcript and visual description</p>
400    <ol class="sebook-teaser-scenes">
401      <li>
402        <span class="sebook-teaser-time">0:00</span>
403        <span class="sebook-teaser-onscreen">On screen: “AI can write the code.”, “build me an app”, “+1,284 lines”</span>
404        <span class="sebook-teaser-visual">A chat box types a request, and generated code streams into an editor while a line counter climbs.</span>
405        <span class="sebook-teaser-sound">Music: Soft synth music; harp notes rise as the request is typed</span>
406      </li>
407      <li>
408        <span class="sebook-teaser-time">0:02</span>
409        <span class="sebook-teaser-onscreen">On screen: “14 undetected bugs”, “Merge conflict in app.py”, “Prod is down 💀”</span>
410        <span class="sebook-teaser-visual">Error notifications slam onto the editor one after another. The editor jolts with each one, its frame glows red, and red squiggles underline the broken code.</span>
411        <span class="sebook-teaser-sound">Music: Driving beat with a harsh chord stab on each alert, then the music winds down like a stopped tape</span>
412      </li>
413      <li>
414        <span class="sebook-teaser-time">0:05</span>
415        <span class="sebook-teaser-onscreen">On screen: “The code was the easy part.”, “Software engineering is everything else.”</span>
416        <span class="sebook-teaser-visual">The editor and notifications fall away. Two lines of text remain, and “everything else” gets a gold underline.</span>
417        <span class="sebook-teaser-sound">Music: Deep bass hit; airy synths build to a drum roll</span>
418      </li>
419      <li>
420        <span class="sebook-teaser-time">0:08</span>
421        <span class="sebook-teaser-onscreen">On screen: “Git”, “branch · merge · push”</span>
422        <span class="sebook-teaser-visual">The view whips sideways to a new panel for each skill. First, a Git history draws itself: a green fix branch dips below the blue main line and a gold feature branch arcs above it; both merge back, and the last commit is tagged v1.0.</span>
423        <span class="sebook-teaser-sound">Music: Upbeat electronic music drops in, with a whoosh at each cut</span>
424      </li>
425      <li>
426        <span class="sebook-teaser-time">0:09</span>
427        <span class="sebook-teaser-onscreen">On screen: “Testing”, “red → green → refactor”</span>
428        <span class="sebook-teaser-visual">Four failing tests, marked with red crosses, flip one by one to passing tests with green check marks.</span>
429      </li>
430      <li>
431        <span class="sebook-teaser-time">0:11</span>
432        <span class="sebook-teaser-onscreen">On screen: “Design patterns”, “code that bends, not breaks”</span>
433        <span class="sebook-teaser-visual">UML class boxes snap together into the Observer pattern: a Subject notifies an Observer interface that two alert classes implement.</span>
434      </li>
435      <li>
436        <span class="sebook-teaser-time">0:12</span>
437        <span class="sebook-teaser-onscreen">On screen: “Architecture”, “systems that scale”</span>
438        <span class="sebook-teaser-visual">Requests flow from a client through an API to a service, which scales out to three copies, and on to a database.</span>
439      </li>
440      <li>
441        <span class="sebook-teaser-time">0:14</span>
442        <span class="sebook-teaser-onscreen">On screen: “Teamwork”, “user stories · Scrum · code review”</span>
443        <span class="sebook-teaser-visual">Story cards slide across a Scrum board from To Do to Done, and a pull request gets approved.</span>
444      </li>
445      <li>
446        <span class="sebook-teaser-time">0:15</span>
447        <span class="sebook-teaser-onscreen">On screen: “Interactive tutorials.”, “Zero setup.”, “Linux terminal”, “time-travel debugger”, “live UML diagrams”</span>
448        <span class="sebook-teaser-visual">A browser window runs a Linux terminal that finds the TODO the AI left in the code, runs the tests, and pushes the fix, while three feature tags pop in.</span>
449        <span class="sebook-teaser-sound">Music: The beat continues and builds</span>
450      </li>
451      <li>
452        <span class="sebook-teaser-time">0:18</span>
453        <span class="sebook-teaser-onscreen">On screen: “SE Book”, “From coder to engineer.”, “tobiasduerschmid.github.io/SEBook”</span>
454        <span class="sebook-teaser-visual">The SE Book logo appears in a soft blue glow, a gold glint runs across its letters, and its tagline and web address follow.</span>
455        <span class="sebook-teaser-sound">Music: Final bass hit; a bright chord rings out</span>
456      </li>
457    </ol>
458  </details>
459</div>
460
461    </div>
462  </div>
463</section>
464
465
466      <!-- Mobile Sidebar Toggle -->
467      <button id="sidebar-toggle" type="button"
468        aria-label="Menu: show table of contents" aria-expanded="false" aria-controls="sidebar">
469        <span aria-hidden="true">☰</span> Menu
470      </button>
471
472      <!-- Sidebar Navigation -->
473      <aside id="sidebar" aria-label="Table of contents">
474        <nav class="sebook-sidebar-nav" aria-label="SE Book table of contents">
475  <ul class="sebook-nav-list">
476    
477    
478    
479    
480    
481    
482    
483    
484    <li class="sebook-nav-item has-subtopics">
485      <div class="sebook-nav-row">
486        <a href="/SEBook/requirements.html" class="sebook-nav-link">
487          
488          <span class="sebook-nav-text">Requirements</span>
489        </a>
490        
491        <button type="button" class="sebook-nav-toggle"
492          aria-expanded="false"
493          aria-controls="sebook-nav-topic-1"
494          aria-label="Toggle Requirements subtopics">
495          <span aria-hidden="true">›</span>
496        </button>
497        
498      </div>
499
500      
501      <ul class="sebook-nav-sublist" id="sebook-nav-topic-1">
502        
503        
504        
505        
506        
507        
508        
509        <li class="sebook-nav-subitem">
510          <div class="sebook-nav-subrow">
511            <a href="/SEBook/userstories.html" class="sebook-nav-sublink">
512              <span class="sebook-nav-text">User Stories</span>
513            </a>
514            
515          </div>
516
517          
518        </li>
519        
520      </ul>
521      
522    </li>
523    
524    
525    
526    
527    
528    
529    
530    <li class="sebook-nav-item has-subtopics">
531      <div class="sebook-nav-row">
532        <a href="/SEBook/designpatterns.html" class="sebook-nav-link">
533          
534          <span class="sebook-nav-text">Design Patterns</span>
535        </a>
536        
537        <button type="button" class="sebook-nav-toggle"
538          aria-expanded="false"
539          aria-controls="sebook-nav-topic-2"
540          aria-label="Toggle Design Patterns subtopics">
541          <span aria-hidden="true">›</span>
542        </button>
543        
544      </div>
545
546      
547      <ul class="sebook-nav-sublist" id="sebook-nav-topic-2">
548        
549        
550        
551        
552        
553        
554        
555        <li class="sebook-nav-subitem">
556          <div class="sebook-nav-subrow">
557            <a href="/SEBook/designpatterns/strategy.html" class="sebook-nav-sublink">
558              <span class="sebook-nav-text">Strategy</span>
559            </a>
560            
561          </div>
562
563          
564        </li>
565        
566        
567        
568        
569        
570        
571        
572        <li class="sebook-nav-subitem">
573          <div class="sebook-nav-subrow">
574            <a href="/SEBook/designpatterns/observer.html" class="sebook-nav-sublink">
575              <span class="sebook-nav-text">Observer</span>
576            </a>
577            
578          </div>
579
580          
581        </li>
582        
583        
584        
585        
586        
587        
588        
589        <li class="sebook-nav-subitem">
590          <div class="sebook-nav-subrow">
591            <a href="/SEBook/designpatterns/command.html" class="sebook-nav-sublink">
592              <span class="sebook-nav-text">Command</span>
593            </a>
594            
595          </div>
596
597          
598        </li>
599        
600        
601        
602        
603        
604        
605        
606        <li class="sebook-nav-subitem">
607          <div class="sebook-nav-subrow">
608            <a href="/SEBook/designpatterns/factory_method.html" class="sebook-nav-sublink">
609              <span class="sebook-nav-text">Factory Method</span>
610            </a>
611            
612          </div>
613
614          
615        </li>
616        
617        
618        
619        
620        
621        
622        
623        <li class="sebook-nav-subitem">
624          <div class="sebook-nav-subrow">
625            <a href="/SEBook/designpatterns/abstract_factory.html" class="sebook-nav-sublink">
626              <span class="sebook-nav-text">Abstract Factory</span>
627            </a>
628            
629          </div>
630
631          
632        </li>
633        
634        
635        
636        
637        
638        
639        
640        <li class="sebook-nav-subitem">
641          <div class="sebook-nav-subrow">
642            <a href="/SEBook/designpatterns/builder.html" class="sebook-nav-sublink">
643              <span class="sebook-nav-text">Builder</span>
644            </a>
645            
646          </div>
647
648          
649        </li>
650        
651        
652        
653        
654        
655        
656        
657        <li class="sebook-nav-subitem">
658          <div class="sebook-nav-subrow">
659            <a href="/SEBook/designpatterns/composite.html" class="sebook-nav-sublink">
660              <span class="sebook-nav-text">Composite</span>
661            </a>
662            
663          </div>
664
665          
666        </li>
667        
668        
669        
670        
671        
672        
673        
674        <li class="sebook-nav-subitem">
675          <div class="sebook-nav-subrow">
676            <a href="/SEBook/designpatterns/state.html" class="sebook-nav-sublink">
677              <span class="sebook-nav-text">State</span>
678            </a>
679            
680          </div>
681
682          
683        </li>
684        
685        
686        
687        
688        
689        
690        
691        <li class="sebook-nav-subitem">
692          <div class="sebook-nav-subrow">
693            <a href="/SEBook/designpatterns/adapter.html" class="sebook-nav-sublink">
694              <span class="sebook-nav-text">Adapter</span>
695            </a>
696            
697          </div>
698
699          
700        </li>
701        
702        
703        
704        
705        
706        
707        
708        <li class="sebook-nav-subitem">
709          <div class="sebook-nav-subrow">
710            <a href="/SEBook/designpatterns/singleton.html" class="sebook-nav-sublink">
711              <span class="sebook-nav-text">Singleton</span>
712            </a>
713            
714          </div>
715
716          
717        </li>
718        
719        
720        
721        
722        
723        
724        
725        <li class="sebook-nav-subitem">
726          <div class="sebook-nav-subrow">
727            <a href="/SEBook/designpatterns/mediator.html" class="sebook-nav-sublink">
728              <span class="sebook-nav-text">Mediator</span>
729            </a>
730            
731          </div>
732
733          
734        </li>
735        
736        
737        
738        
739        
740        
741        
742        <li class="sebook-nav-subitem">
743          <div class="sebook-nav-subrow">
744            <a href="/SEBook/designpatterns/visitor.html" class="sebook-nav-sublink">
745              <span class="sebook-nav-text">Visitor</span>
746            </a>
747            
748          </div>
749
750          
751        </li>
752        
753        
754        
755        
756        
757        
758        
759        <li class="sebook-nav-subitem">
760          <div class="sebook-nav-subrow">
761            <a href="/SEBook/designpatterns/facade.html" class="sebook-nav-sublink">
762              <span class="sebook-nav-text">Facade</span>
763            </a>
764            
765          </div>
766
767          
768        </li>
769        
770        
771        
772        
773        
774        
775        
776        <li class="sebook-nav-subitem">
777          <div class="sebook-nav-subrow">
778            <a href="/SEBook/designpatterns/mvc.html" class="sebook-nav-sublink">
779              <span class="sebook-nav-text">Model-View-Controller (MVC)</span>
780            </a>
781            
782          </div>
783
784          
785        </li>
786        
787      </ul>
788      
789    </li>
790    
791    
792    
793    
794    
795    
796    
797    <li class="sebook-nav-item has-subtopics">
798      <div class="sebook-nav-row">
799        <a href="/SEBook/designprinciples/index.html" class="sebook-nav-link">
800          
801          <span class="sebook-nav-text">Design Principles</span>
802        </a>
803        
804        <button type="button" class="sebook-nav-toggle"
805          aria-expanded="false"
806          aria-controls="sebook-nav-topic-3"
807          aria-label="Toggle Design Principles subtopics">
808          <span aria-hidden="true">›</span>
809        </button>
810        
811      </div>
812
813      
814      <ul class="sebook-nav-sublist" id="sebook-nav-topic-3">
815        
816        
817        
818        
819        
820        
821        
822        <li class="sebook-nav-subitem">
823          <div class="sebook-nav-subrow">
824            <a href="/SEBook/designprinciples/soc.html" class="sebook-nav-sublink">
825              <span class="sebook-nav-text">Separation of Concerns</span>
826            </a>
827            
828          </div>
829
830          
831        </li>
832        
833        
834        
835        
836        
837        
838        
839        <li class="sebook-nav-subitem">
840          <div class="sebook-nav-subrow">
841            <a href="/SEBook/designprinciples/informationhiding.html" class="sebook-nav-sublink">
842              <span class="sebook-nav-text">Information Hiding</span>
843            </a>
844            
845          </div>
846
847          
848        </li>
849        
850        
851        
852        
853        
854        
855        
856        <li class="sebook-nav-subitem">
857          <div class="sebook-nav-subrow">
858            <a href="/SEBook/designprinciples/solid.html" class="sebook-nav-sublink">
859              <span class="sebook-nav-text">SOLID</span>
860            </a>
861            
862          </div>
863
864          
865        </li>
866        
867        
868        
869        
870        
871        
872        
873        <li class="sebook-nav-subitem">
874          <div class="sebook-nav-subrow">
875            <a href="/SEBook/designprinciples/reuse.html" class="sebook-nav-sublink">
876              <span class="sebook-nav-text">Design with Reuse</span>
877            </a>
878            
879          </div>
880
881          
882        </li>
883        
884      </ul>
885      
886    </li>
887    
888    
889    
890    
891    
892    
893    
894    <li class="sebook-nav-item has-subtopics">
895      <div class="sebook-nav-row">
896        <a href="/SEBook/software_architecture.html" class="sebook-nav-link">
897          
898          <span class="sebook-nav-text">Software Architecture</span>
899        </a>
900        
901        <button type="button" class="sebook-nav-toggle"
902          aria-expanded="false"
903          aria-controls="sebook-nav-topic-4"
904          aria-label="Toggle Software Architecture subtopics">
905          <span aria-hidden="true">›</span>
906        </button>
907        
908      </div>
909
910      
911      <ul class="sebook-nav-sublist" id="sebook-nav-topic-4">
912        
913        
914        
915        
916        
917        
918        
919        <li class="sebook-nav-subitem has-subitems">
920          <div class="sebook-nav-subrow">
921            <a href="/SEBook/quality_attributes.html" class="sebook-nav-sublink">
922              <span class="sebook-nav-text">Quality Attributes</span>
923            </a>
924            
925            <button type="button" class="sebook-nav-toggle"
926              aria-expanded="false"
927              aria-controls="sebook-nav-topic-4-subtopic-1"
928              aria-label="Toggle Quality Attributes subtopics">
929              <span aria-hidden="true">›</span>
930            </button>
931            
932          </div>
933
934          
935          <ul class="sebook-nav-itemlist" id="sebook-nav-topic-4-subtopic-1">
936            
937            
938            
939            
940            <li class="sebook-nav-item-leaf">
941              <a href="/SEBook/quality_attributes/interoperability.html" class="sebook-nav-itemlink">
942                Interoperability
943              </a>
944            </li>
945            
946            
947            
948            
949            <li class="sebook-nav-item-leaf">
950              <a href="/SEBook/quality_attributes/testability.html" class="sebook-nav-itemlink">
951                Testability
952              </a>
953            </li>
954            
955          </ul>
956          
957        </li>
958        
959        
960        
961        
962        
963        
964        
965        <li class="sebook-nav-subitem">
966          <div class="sebook-nav-subrow">
967            <a href="/SEBook/architectural_tactics.html" class="sebook-nav-sublink">
968              <span class="sebook-nav-text">Architectural Tactics</span>
969            </a>
970            
971          </div>
972
973          
974        </li>
975        
976        
977        
978        
979        
980        
981        
982        <li class="sebook-nav-subitem has-subitems">
983          <div class="sebook-nav-subrow">
984            <a href="/SEBook/architectural_styles/index.html" class="sebook-nav-sublink">
985              <span class="sebook-nav-text">Architectural Styles</span>
986            </a>
987            
988            <button type="button" class="sebook-nav-toggle"
989              aria-expanded="false"
990              aria-controls="sebook-nav-topic-4-subtopic-3"
991              aria-label="Toggle Architectural Styles subtopics">
992              <span aria-hidden="true">›</span>
993            </button>
994            
995          </div>
996
997          
998          <ul class="sebook-nav-itemlist" id="sebook-nav-topic-4-subtopic-3">
999            
1000            
1001            
1002            
1003            <li class="sebook-nav-item-leaf">
1004              <a href="/SEBook/architectural_styles/layers.html" class="sebook-nav-itemlink">
1005                Layered Style
1006              </a>
1007            </li>
1008            
1009            
1010            
1011            
1012            <li class="sebook-nav-item-leaf">
1013              <a href="/SEBook/architectural_styles/pipes_and_filters.html" class="sebook-nav-itemlink">
1014                Pipes and Filters
1015              </a>
1016            </li>
1017            
1018            
1019            
1020            
1021            <li class="sebook-nav-item-leaf">
1022              <a href="/SEBook/architectural_styles/pubsub.html" class="sebook-nav-itemlink">
1023                Publish Subscribe
1024              </a>
1025            </li>
1026            
1027          </ul>
1028          
1029        </li>
1030        
1031      </ul>
1032      
1033    </li>
1034    
1035    
1036    
1037    
1038    
1039    
1040    
1041    <li class="sebook-nav-item has-subtopics">
1042      <div class="sebook-nav-row">
1043        <a href="/SEBook/process.html" class="sebook-nav-link">
1044          
1045          <span class="sebook-nav-text">Software Process</span>
1046        </a>
1047        
1048        <button type="button" class="sebook-nav-toggle"
1049          aria-expanded="false"
1050          aria-controls="sebook-nav-topic-5"
1051          aria-label="Toggle Software Process subtopics">
1052          <span aria-hidden="true">›</span>
1053        </button>
1054        
1055      </div>
1056
1057      
1058      <ul class="sebook-nav-sublist" id="sebook-nav-topic-5">
1059        
1060        
1061        
1062        
1063        
1064        
1065        
1066        <li class="sebook-nav-subitem">
1067          <div class="sebook-nav-subrow">
1068            <a href="/SEBook/process/scrum.html" class="sebook-nav-sublink">
1069              <span class="sebook-nav-text">Scrum</span>
1070            </a>
1071            
1072          </div>
1073
1074          
1075        </li>
1076        
1077        
1078        
1079        
1080        
1081        
1082        
1083        <li class="sebook-nav-subitem">
1084          <div class="sebook-nav-subrow">
1085            <a href="/SEBook/process/xp.html" class="sebook-nav-sublink">
1086              <span class="sebook-nav-text">Extreme Programming (XP)</span>
1087            </a>
1088            
1089          </div>
1090
1091          
1092        </li>
1093        
1094        
1095        
1096        
1097        
1098        
1099        
1100        <li class="sebook-nav-subitem">
1101          <div class="sebook-nav-subrow">
1102            <a href="/SEBook/process/people-and-processes.html" class="sebook-nav-sublink">
1103              <span class="sebook-nav-text">People and Processes</span>
1104            </a>
1105            
1106          </div>
1107
1108          
1109        </li>
1110        
1111      </ul>
1112      
1113    </li>
1114    
1115    
1116    
1117    
1118    
1119    
1120    
1121    <li class="sebook-nav-item has-subtopics">
1122      <div class="sebook-nav-row">
1123        <a href="/SEBook/testing.html" class="sebook-nav-link">
1124          
1125          <span class="sebook-nav-text">Testing</span>
1126        </a>
1127        
1128        <button type="button" class="sebook-nav-toggle"
1129          aria-expanded="false"
1130          aria-controls="sebook-nav-topic-6"
1131          aria-label="Toggle Testing subtopics">
1132          <span aria-hidden="true">›</span>
1133        </button>
1134        
1135      </div>
1136
1137      
1138      <ul class="sebook-nav-sublist" id="sebook-nav-topic-6">
1139        
1140        
1141        
1142        
1143        
1144        
1145        
1146        <li class="sebook-nav-subitem">
1147          <div class="sebook-nav-subrow">
1148            <a href="/SEBook/testing/testquality.html" class="sebook-nav-sublink">
1149              <span class="sebook-nav-text">Test Quality</span>
1150            </a>
1151            
1152          </div>
1153
1154          
1155        </li>
1156        
1157        
1158        
1159        
1160        
1161        
1162        
1163        <li class="sebook-nav-subitem">
1164          <div class="sebook-nav-subrow">
1165            <a href="/SEBook/testing/goodtests.html" class="sebook-nav-sublink">
1166              <span class="sebook-nav-text">Writing Good Tests</span>
1167            </a>
1168            
1169          </div>
1170
1171          
1172        </li>
1173        
1174        
1175        
1176        
1177        
1178        
1179        
1180        <li class="sebook-nav-subitem">
1181          <div class="sebook-nav-subrow">
1182            <a href="/SEBook/testing/testing-foundations-tutorial.html" class="sebook-nav-sublink">
1183              <span class="sebook-nav-text">Testing Foundations Tutorial</span>
1184            </a>
1185            
1186          </div>
1187
1188          
1189        </li>
1190        
1191        
1192        
1193        
1194        
1195        
1196        
1197        <li class="sebook-nav-subitem">
1198          <div class="sebook-nav-subrow">
1199            <a href="/SEBook/testing/tdd.html" class="sebook-nav-sublink">
1200              <span class="sebook-nav-text">Test-Driven Development (TDD)</span>
1201            </a>
1202            
1203          </div>
1204
1205          
1206        </li>
1207        
1208        
1209        
1210        
1211        
1212        
1213        
1214        <li class="sebook-nav-subitem">
1215          <div class="sebook-nav-subrow">
1216            <a href="/SEBook/testing/tdd-tutorial.html" class="sebook-nav-sublink">
1217              <span class="sebook-nav-text">TDD Tutorial</span>
1218            </a>
1219            
1220          </div>
1221
1222          
1223        </li>
1224        
1225        
1226        
1227        
1228        
1229        
1230        
1231        <li class="sebook-nav-subitem">
1232          <div class="sebook-nav-subrow">
1233            <a href="/SEBook/testing/testdoubles.html" class="sebook-nav-sublink">
1234              <span class="sebook-nav-text">Test Doubles</span>
1235            </a>
1236            
1237          </div>
1238
1239          
1240        </li>
1241        
1242        
1243        
1244        
1245        
1246        
1247        
1248        <li class="sebook-nav-subitem">
1249          <div class="sebook-nav-subrow">
1250            <a href="/SEBook/testing/test-doubles-tutorial.html" class="sebook-nav-sublink">
1251              <span class="sebook-nav-text">Test Doubles Tutorial</span>
1252            </a>
1253            
1254          </div>
1255
1256          
1257        </li>
1258        
1259      </ul>
1260      
1261    </li>
1262    
1263    
1264    
1265    
1266    
1267    
1268    
1269    <li class="sebook-nav-item has-subtopics">
1270      <div class="sebook-nav-row">
1271        <a href="/SEBook/uml.html" class="sebook-nav-link">
1272          
1273          <span class="sebook-nav-text">UML</span>
1274        </a>
1275        
1276        <button type="button" class="sebook-nav-toggle"
1277          aria-expanded="false"
1278          aria-controls="sebook-nav-topic-7"
1279          aria-label="Toggle UML subtopics">
1280          <span aria-hidden="true">›</span>
1281        </button>
1282        
1283      </div>
1284
1285      
1286      <ul class="sebook-nav-sublist" id="sebook-nav-topic-7">
1287        
1288        
1289        
1290        
1291        
1292        
1293        
1294        <li class="sebook-nav-subitem">
1295          <div class="sebook-nav-subrow">
1296            <a href="/SEBook/tools/uml-editor.html" class="sebook-nav-sublink">
1297              <span class="sebook-nav-text">UML Editor</span>
1298            </a>
1299            
1300          </div>
1301
1302          
1303        </li>
1304        
1305        
1306        
1307        
1308        
1309        
1310        
1311        <li class="sebook-nav-subitem">
1312          <div class="sebook-nav-subrow">
1313            <a href="/SEBook/uml_use_case_diagram.html" class="sebook-nav-sublink">
1314              <span class="sebook-nav-text">Use Case Diagrams</span>
1315            </a>
1316            
1317          </div>
1318
1319          
1320        </li>
1321        
1322        
1323        
1324        
1325        
1326        
1327        
1328        <li class="sebook-nav-subitem">
1329          <div class="sebook-nav-subrow">
1330            <a href="/SEBook/uml_class_diagram.html" class="sebook-nav-sublink">
1331              <span class="sebook-nav-text">Class Diagrams</span>
1332            </a>
1333            
1334          </div>
1335
1336          
1337        </li>
1338        
1339        
1340        
1341        
1342        
1343        
1344        
1345        <li class="sebook-nav-subitem">
1346          <div class="sebook-nav-subrow">
1347            <a href="/SEBook/uml_sequence_diagram.html" class="sebook-nav-sublink">
1348              <span class="sebook-nav-text">Sequence Diagrams</span>
1349            </a>
1350            
1351          </div>
1352
1353          
1354        </li>
1355        
1356        
1357        
1358        
1359        
1360        
1361        
1362        <li class="sebook-nav-subitem">
1363          <div class="sebook-nav-subrow">
1364            <a href="/SEBook/uml_state_diagram.html" class="sebook-nav-sublink">
1365              <span class="sebook-nav-text">State Machine Diagrams</span>
1366            </a>
1367            
1368          </div>
1369
1370          
1371        </li>
1372        
1373        
1374        
1375        
1376        
1377        
1378        
1379        <li class="sebook-nav-subitem">
1380          <div class="sebook-nav-subrow">
1381            <a href="/SEBook/uml_component_diagram.html" class="sebook-nav-sublink">
1382              <span class="sebook-nav-text">Component Diagrams</span>
1383            </a>
1384            
1385          </div>
1386
1387          
1388        </li>
1389        
1390      </ul>
1391      
1392    </li>
1393    
1394    
1395    
1396    
1397    
1398    
1399    
1400    <li class="sebook-nav-item has-subtopics">
1401      <div class="sebook-nav-row">
1402        <a href="/SEBook/development_practices/index.html" class="sebook-nav-link">
1403          
1404          <span class="sebook-nav-text">Development Practices</span>
1405        </a>
1406        
1407        <button type="button" class="sebook-nav-toggle"
1408          aria-expanded="false"
1409          aria-controls="sebook-nav-topic-8"
1410          aria-label="Toggle Development Practices subtopics">
1411          <span aria-hidden="true">›</span>
1412        </button>
1413        
1414      </div>
1415
1416      
1417      <ul class="sebook-nav-sublist" id="sebook-nav-topic-8">
1418        
1419        
1420        
1421        
1422        
1423        
1424        
1425        <li class="sebook-nav-subitem">
1426          <div class="sebook-nav-subrow">
1427            <a href="/SEBook/development_practices/beacons.html" class="sebook-nav-sublink">
1428              <span class="sebook-nav-text">Beacons</span>
1429            </a>
1430            
1431          </div>
1432
1433          
1434        </li>
1435        
1436        
1437        
1438        
1439        
1440        
1441        
1442        <li class="sebook-nav-subitem">
1443          <div class="sebook-nav-subrow">
1444            <a href="/SEBook/development_practices/code_comprehension.html" class="sebook-nav-sublink">
1445              <span class="sebook-nav-text">Code Comprehension</span>
1446            </a>
1447            
1448          </div>
1449
1450          
1451        </li>
1452        
1453        
1454        
1455        
1456        
1457        
1458        
1459        <li class="sebook-nav-subitem">
1460          <div class="sebook-nav-subrow">
1461            <a href="/SEBook/development_practices/debugging.html" class="sebook-nav-sublink">
1462              <span class="sebook-nav-text">Debugging</span>
1463            </a>
1464            
1465          </div>
1466
1467          
1468        </li>
1469        
1470        
1471        
1472        
1473        
1474        
1475        
1476        <li class="sebook-nav-subitem">
1477          <div class="sebook-nav-subrow">
1478            <a href="/SEBook/tools/python-debugging.html" class="sebook-nav-sublink">
1479              <span class="sebook-nav-text">Python Debugging Tutorial</span>
1480            </a>
1481            
1482          </div>
1483
1484          
1485        </li>
1486        
1487        
1488        
1489        
1490        
1491        
1492        
1493        <li class="sebook-nav-subitem">
1494          <div class="sebook-nav-subrow">
1495            <a href="/SEBook/development_practices/genAI.html" class="sebook-nav-sublink">
1496              <span class="sebook-nav-text">Gen Ai</span>
1497            </a>
1498            
1499          </div>
1500
1501          
1502        </li>
1503        
1504        
1505        
1506        
1507        
1508        
1509        
1510        <li class="sebook-nav-subitem">
1511          <div class="sebook-nav-subrow">
1512            <a href="/SEBook/development_practices/modern_code_review.html" class="sebook-nav-sublink">
1513              <span class="sebook-nav-text">Modern Code Review</span>
1514            </a>
1515            
1516          </div>
1517
1518          
1519        </li>
1520        
1521        
1522        
1523        
1524        
1525        
1526        
1527        <li class="sebook-nav-subitem">
1528          <div class="sebook-nav-subrow">
1529            <a href="/SEBook/development_practices/promptengineering.html" class="sebook-nav-sublink">
1530              <span class="sebook-nav-text">Prompt Engineering</span>
1531            </a>
1532            
1533          </div>
1534
1535          
1536        </li>
1537        
1538        
1539        
1540        
1541        
1542        
1543        
1544        <li class="sebook-nav-subitem">
1545          <div class="sebook-nav-subrow">
1546            <a href="/SEBook/development_practices/code_smells.html" class="sebook-nav-sublink">
1547              <span class="sebook-nav-text">Code Smells</span>
1548            </a>
1549            
1550          </div>
1551
1552          
1553        </li>
1554        
1555        
1556        
1557        
1558        
1559        
1560        
1561        <li class="sebook-nav-subitem">
1562          <div class="sebook-nav-subrow">
1563            <a href="/SEBook/development_practices/refactoring.html" class="sebook-nav-sublink">
1564              <span class="sebook-nav-text">Refactoring</span>
1565            </a>
1566            
1567          </div>
1568
1569          
1570        </li>
1571        
1572        
1573        
1574        
1575        
1576        
1577        
1578        <li class="sebook-nav-subitem">
1579          <div class="sebook-nav-subrow">
1580            <a href="/SEBook/tools/code-smells-refactoring-tutorial.html" class="sebook-nav-sublink">
1581              <span class="sebook-nav-text">Code Smells & Refactoring Tutorial</span>
1582            </a>
1583            
1584          </div>
1585
1586          
1587        </li>
1588        
1589        
1590        
1591        
1592        
1593        
1594        
1595        <li class="sebook-nav-subitem">
1596          <div class="sebook-nav-subrow">
1597            <a href="/SEBook/development_practices/topdown.html" class="sebook-nav-sublink">
1598              <span class="sebook-nav-text">Top Down Code Comprehension</span>
1599            </a>
1600            
1601          </div>
1602
1603          
1604        </li>
1605        
1606      </ul>
1607      
1608    </li>
1609    
1610    
1611    
1612    
1613    
1614    
1615    
1616    <li class="sebook-nav-item has-subtopics">
1617      <div class="sebook-nav-row">
1618        <a href="/SEBook/tools/index.html" class="sebook-nav-link">
1619          
1620          <span class="sebook-nav-text">Tools</span>
1621        </a>
1622        
1623        <button type="button" class="sebook-nav-toggle"
1624          aria-expanded="false"
1625          aria-controls="sebook-nav-topic-9"
1626          aria-label="Toggle Tools subtopics">
1627          <span aria-hidden="true">›</span>
1628        </button>
1629        
1630      </div>
1631
1632      
1633      <ul class="sebook-nav-sublist" id="sebook-nav-topic-9">
1634        
1635        
1636        
1637        
1638        
1639        
1640        
1641        <li class="sebook-nav-subitem">
1642          <div class="sebook-nav-subrow">
1643            <a href="/SEBook/tools/shell.html" class="sebook-nav-sublink">
1644              <span class="sebook-nav-text">Shell Scripting</span>
1645            </a>
1646            
1647          </div>
1648
1649          
1650        </li>
1651        
1652        
1653        
1654        
1655        
1656        
1657        
1658        <li class="sebook-nav-subitem">
1659          <div class="sebook-nav-subrow">
1660            <a href="/SEBook/tools/shell-tutorial.html" class="sebook-nav-sublink">
1661              <span class="sebook-nav-text">Shell Scripting Tutorial</span>
1662            </a>
1663            
1664          </div>
1665
1666          
1667        </li>
1668        
1669        
1670        
1671        
1672        
1673        
1674        
1675        <li class="sebook-nav-subitem">
1676          <div class="sebook-nav-subrow">
1677            <a href="/SEBook/tools/regex.html" class="sebook-nav-sublink">
1678              <span class="sebook-nav-text">Regular Expressions</span>
1679            </a>
1680            
1681          </div>
1682
1683          
1684        </li>
1685        
1686        
1687        
1688        
1689        
1690        
1691        
1692        <li class="sebook-nav-subitem">
1693          <div class="sebook-nav-subrow">
1694            <a href="/SEBook/tools/regex-simulator.html" class="sebook-nav-sublink">
1695              <span class="sebook-nav-text">Python RegEx Simulator & Debugger</span>
1696            </a>
1697            
1698          </div>
1699
1700          
1701        </li>
1702        
1703        
1704        
1705        
1706        
1707        
1708        
1709        <li class="sebook-nav-subitem">
1710          <div class="sebook-nav-subrow">
1711            <a href="/SEBook/tools/regex-tutorial.html" class="sebook-nav-sublink">
1712              <span class="sebook-nav-text">RegEx Tutorial: Basics</span>
1713            </a>
1714            
1715          </div>
1716
1717          
1718        </li>
1719        
1720        
1721        
1722        
1723        
1724        
1725        
1726        <li class="sebook-nav-subitem">
1727          <div class="sebook-nav-subrow">
1728            <a href="/SEBook/tools/regex-tutorial-advanced.html" class="sebook-nav-sublink">
1729              <span class="sebook-nav-text">RegEx Tutorial: Advanced</span>
1730            </a>
1731            
1732          </div>
1733
1734          
1735        </li>
1736        
1737        
1738        
1739        
1740        
1741        
1742        
1743        <li class="sebook-nav-subitem">
1744          <div class="sebook-nav-subrow">
1745            <a href="/SEBook/tools/python.html" class="sebook-nav-sublink">
1746              <span class="sebook-nav-text">Python</span>
1747            </a>
1748            
1749          </div>
1750
1751          
1752        </li>
1753        
1754        
1755        
1756        
1757        
1758        
1759        
1760        <li class="sebook-nav-subitem">
1761          <div class="sebook-nav-subrow">
1762            <a href="/SEBook/tools/python-tutorial.html" class="sebook-nav-sublink">
1763              <span class="sebook-nav-text">Python Tutorial</span>
1764            </a>
1765            
1766          </div>
1767
1768          
1769        </li>
1770        
1771        
1772        
1773        
1774        
1775        
1776        
1777        <li class="sebook-nav-subitem">
1778          <div class="sebook-nav-subrow">
1779            <a href="/SEBook/tools/haskell.html" class="sebook-nav-sublink">
1780              <span class="sebook-nav-text">Haskell</span>
1781            </a>
1782            
1783          </div>
1784
1785          
1786        </li>
1787        
1788        
1789        
1790        
1791        
1792        
1793        
1794        <li class="sebook-nav-subitem">
1795          <div class="sebook-nav-subrow">
1796            <a href="/SEBook/tools/nodejs.html" class="sebook-nav-sublink">
1797              <span class="sebook-nav-text">Node.js</span>
1798            </a>
1799            
1800          </div>
1801
1802          
1803        </li>
1804        
1805        
1806        
1807        
1808        
1809        
1810        
1811        <li class="sebook-nav-subitem">
1812          <div class="sebook-nav-subrow">
1813            <a href="/SEBook/tools/nodejs-tutorial.html" class="sebook-nav-sublink">
1814              <span class="sebook-nav-text">Node.js Tutorial</span>
1815            </a>
1816            
1817          </div>
1818
1819          
1820        </li>
1821        
1822        
1823        
1824        
1825        
1826        
1827        
1828        <li class="sebook-nav-subitem">
1829          <div class="sebook-nav-subrow">
1830            <a href="/SEBook/tools/react.html" class="sebook-nav-sublink">
1831              <span class="sebook-nav-text">React</span>
1832            </a>
1833            
1834          </div>
1835
1836          
1837        </li>
1838        
1839        
1840        
1841        
1842        
1843        
1844        
1845        <li class="sebook-nav-subitem">
1846          <div class="sebook-nav-subrow">
1847            <a href="/SEBook/tools/react-tutorial.html" class="sebook-nav-sublink">
1848              <span class="sebook-nav-text">React Tutorial</span>
1849            </a>
1850            
1851          </div>
1852
1853          
1854        </li>
1855        
1856        
1857        
1858        
1859        
1860        
1861        
1862        <li class="sebook-nav-subitem">
1863          <div class="sebook-nav-subrow">
1864            <a href="/SEBook/tools/git.html" class="sebook-nav-sublink">
1865              <span class="sebook-nav-text">Git</span>
1866            </a>
1867            
1868          </div>
1869
1870          
1871        </li>
1872        
1873        
1874        
1875        
1876        
1877        
1878        
1879        <li class="sebook-nav-subitem">
1880          <div class="sebook-nav-subrow">
1881            <a href="/SEBook/tools/git-tutorial.html" class="sebook-nav-sublink">
1882              <span class="sebook-nav-text">Git Tutorial</span>
1883            </a>
1884            
1885          </div>
1886
1887          
1888        </li>
1889        
1890        
1891        
1892        
1893        
1894        
1895        
1896        <li class="sebook-nav-subitem">
1897          <div class="sebook-nav-subrow">
1898            <a href="/SEBook/tools/java.html" class="sebook-nav-sublink">
1899              <span class="sebook-nav-text">Java</span>
1900            </a>
1901            
1902          </div>
1903
1904          
1905        </li>
1906        
1907        
1908        
1909        
1910        
1911        
1912        
1913        <li class="sebook-nav-subitem">
1914          <div class="sebook-nav-subrow">
1915            <a href="/SEBook/tools/java-tutorial.html" class="sebook-nav-sublink">
1916              <span class="sebook-nav-text">Java Tutorial</span>
1917            </a>
1918            
1919          </div>
1920
1921          
1922        </li>
1923        
1924        
1925        
1926        
1927        
1928        
1929        
1930        <li class="sebook-nav-subitem">
1931          <div class="sebook-nav-subrow">
1932            <a href="/SEBook/tools/java-cs131-tutorial" class="sebook-nav-sublink">
1933              <span class="sebook-nav-text">Java Concepts for CS131</span>
1934            </a>
1935            
1936          </div>
1937
1938          
1939        </li>
1940        
1941        
1942        
1943        
1944        
1945        
1946        
1947        <li class="sebook-nav-subitem">
1948          <div class="sebook-nav-subrow">
1949            <a href="/SEBook/tools/c.html" class="sebook-nav-sublink">
1950              <span class="sebook-nav-text">C Programming</span>
1951            </a>
1952            
1953          </div>
1954
1955          
1956        </li>
1957        
1958        
1959        
1960        
1961        
1962        
1963        
1964        <li class="sebook-nav-subitem">
1965          <div class="sebook-nav-subrow">
1966            <a href="/SEBook/tools/c-tutorial.html" class="sebook-nav-sublink">
1967              <span class="sebook-nav-text">C for C++ Programmers Tutorial</span>
1968            </a>
1969            
1970          </div>
1971
1972          
1973        </li>
1974        
1975        
1976        
1977        
1978        
1979        
1980        
1981        <li class="sebook-nav-subitem">
1982          <div class="sebook-nav-subrow">
1983            <a href="/SEBook/tools/make.html" class="sebook-nav-sublink">
1984              <span class="sebook-nav-text">Make</span>
1985            </a>
1986            
1987          </div>
1988
1989          
1990        </li>
1991        
1992        
1993        
1994        
1995        
1996        
1997        
1998        <li class="sebook-nav-subitem">
1999          <div class="sebook-nav-subrow">
2000            <a href="/SEBook/tools/makefile-tutorial.html" class="sebook-nav-sublink">
2001              <span class="sebook-nav-text">Makefile Tutorial</span>
2002            </a>
2003            
2004          </div>
2005
2006          
2007        </li>
2008        
2009        
2010        
2011        
2012        
2013        
2014        
2015        <li class="sebook-nav-subitem">
2016          <div class="sebook-nav-subrow">
2017            <a href="/SEBook/tools/playwright-tutorial.html" class="sebook-nav-sublink">
2018              <span class="sebook-nav-text">Playwright Tutorial</span>
2019            </a>
2020            
2021          </div>
2022
2023          
2024        </li>
2025        
2026      </ul>
2027      
2028    </li>
2029    
2030    
2031    
2032    
2033    
2034    
2035    
2036    <li class="sebook-nav-item has-subtopics">
2037      <div class="sebook-nav-row">
2038        <a href="/SEBook/systems/index.html" class="sebook-nav-link">
2039          
2040          <span class="sebook-nav-text">Systems</span>
2041        </a>
2042        
2043        <button type="button" class="sebook-nav-toggle"
2044          aria-expanded="false"
2045          aria-controls="sebook-nav-topic-10"
2046          aria-label="Toggle Systems subtopics">
2047          <span aria-hidden="true">›</span>
2048        </button>
2049        
2050      </div>
2051
2052      
2053      <ul class="sebook-nav-sublist" id="sebook-nav-topic-10">
2054        
2055        
2056        
2057        
2058        
2059        
2060        
2061        <li class="sebook-nav-subitem">
2062          <div class="sebook-nav-subrow">
2063            <a href="/SEBook/tools/networking.html" class="sebook-nav-sublink">
2064              <span class="sebook-nav-text">Networking</span>
2065            </a>
2066            
2067          </div>
2068
2069          
2070        </li>
2071        
2072        
2073        
2074        
2075        
2076        
2077        
2078        <li class="sebook-nav-subitem">
2079          <div class="sebook-nav-subrow">
2080            <a href="/SEBook/systems/data_management.html" class="sebook-nav-sublink">
2081              <span class="sebook-nav-text">Data Management</span>
2082            </a>
2083            
2084          </div>
2085
2086          
2087        </li>
2088        
2089        
2090        
2091        
2092        
2093        
2094        
2095        <li class="sebook-nav-subitem">
2096          <div class="sebook-nav-subrow">
2097            <a href="/SEBook/systems/security.html" class="sebook-nav-sublink">
2098              <span class="sebook-nav-text">Security and Authentication</span>
2099            </a>
2100            
2101          </div>
2102
2103          
2104        </li>
2105        
2106      </ul>
2107      
2108    </li>
2109    
2110    
2111    
2112    
2113    
2114    
2115    
2116    <li class="sebook-nav-item">
2117      <div class="sebook-nav-row">
2118        <a href="/se-gym/" class="sebook-nav-link">
2119          
2120          <span class="sebook-nav-text">SE Gym</span>
2121        </a>
2122        
2123      </div>
2124
2125      
2126    </li>
2127    
2128    
2129    
2130    
2131    
2132    
2133    
2134    <li class="sebook-nav-item has-subtopics">
2135      <div class="sebook-nav-row">
2136        <a href="/SEBook/bookmarks.html" class="sebook-nav-link">
2137          
2138          <span class="sebook-nav-text">Bookmarks</span>
2139        </a>
2140        
2141        <button type="button" class="sebook-nav-toggle"
2142          aria-expanded="false"
2143          aria-controls="sebook-nav-topic-12"
2144          aria-label="Toggle Bookmarks subtopics">
2145          <span aria-hidden="true">›</span>
2146        </button>
2147        
2148      </div>
2149
2150      
2151      <ul class="sebook-nav-sublist" id="sebook-nav-topic-12">
2152        
2153        
2154        
2155        
2156        
2157        
2158        
2159        <li class="sebook-nav-subitem">
2160          <div class="sebook-nav-subrow">
2161            <a href="/SEBook/CS35L_bookmarks.html" class="sebook-nav-sublink">
2162              <span class="sebook-nav-text">CS 35L Bookmarks</span>
2163            </a>
2164            
2165          </div>
2166
2167          
2168        </li>
2169        
2170        
2171        
2172        
2173        
2174        
2175        
2176        <li class="sebook-nav-subitem">
2177          <div class="sebook-nav-subrow">
2178            <a href="/SEBook/CS130_bookmarks.html" class="sebook-nav-sublink">
2179              <span class="sebook-nav-text">CS 130 Bookmarks</span>
2180            </a>
2181            
2182          </div>
2183
2184          
2185        </li>
2186        
2187        
2188        
2189        
2190        
2191        
2192        
2193        <li class="sebook-nav-subitem">
2194          <div class="sebook-nav-subrow">
2195            <a href="/SEBook/CS131_bookmarks.html" class="sebook-nav-sublink">
2196              <span class="sebook-nav-text">CS 131 Bookmarks</span>
2197            </a>
2198            
2199          </div>
2200
2201          
2202        </li>
2203        
2204      </ul>
2205      
2206    </li>
2207    
2208  </ul>
2209</nav>
2210
2211      </aside>
2212
2213      <!-- Main Content -->
2214      <main id="main-content" tabindex="-1">
2215        
2216
2217        <!-- Toggles -->
2218        <div class="highlight-toggle-container is-hidden" id="togglesContainer">
2219          <div class="toggle-control-row">
2220            <span class="toggle-label">Dark Mode</span>
2221            <label class="switch">
2222              <span class="sr-only">Toggle dark mode</span>
2223              <input type="checkbox" id="darkModeToggle" aria-label="Toggle dark mode">
2224              <span class="slider round"></span>
2225            </label>
2226          </div>
2227          <div class="toggle-control-row is-spaced">
2228            <span class="toggle-label">Show Highlights</span>
2229            <label class="switch">
2230              <span class="sr-only">Toggle highlights</span>
2231              <input type="checkbox" id="highlightToggle" checked aria-label="Toggle highlights">
2232              <span class="slider round"></span>
2233            </label>
2234          </div>
2235          <div class="toggle-control-row">
2236            <span class="toggle-label">Read Aloud</span>
2237            <label class="switch">
2238              <span class="sr-only">Toggle read aloud</span>
2239              <input type="checkbox" id="readAloudToggle" checked aria-label="Toggle read aloud">
2240              <span class="slider round"></span>
2241            </label>
2242          </div>
2243          <div class="toggle-control-row">
2244            <button id="tts-read-btn" aria-label="Read Aloud: read page aloud using text-to-speech"
2245              type="button">
2246              <i class="fa fa-volume-up tts-read-inline-icon" aria-hidden="true"></i>Read Aloud
2247            </button>
2248          </div>
2249          
2250          <div id="bookmarkBtnWrapper" class="is-hidden" data-page-title="SE Book — Table of Contents">
2251            <button id="bookmarkPageBtn" aria-label="Bookmark this page" type="button">
2252              <i id="bookmarkIcon" class="fa-regular fa-bookmark" aria-hidden="true"></i>
2253            </button>
2254          </div>
2255          
2256        </div>
2257
2258        <div class="container" role="region" aria-label="SE Book — Table of Contents introduction">
2259          <div class="row">
2260            
2261              
2262              
2263              
2264                  
2265                
2266              
2267              <section id="table-of-contents">
2268              <h1>Table of Contents</h1>
2269
2270<section id="sebook-search" aria-labelledby="sebook-search-heading" class="sebook-search">
2271  <h2 id="sebook-search-heading">Search the SE Book</h2>
2272  <div class="sebook-search-controls">
2273    <label for="sebook-search-input" class="sebook-search-label">
2274      Find a section or tutorial
2275    </label>
2276    <div class="sebook-search-input-wrap">
2277      <input type="search" id="sebook-search-input" class="sebook-search-input" placeholder="Type to filter section and tutorial titles…" autocomplete="off" spellcheck="false" aria-describedby="sebook-search-hint sebook-search-summary" aria-controls="sebook-search-results" />
2278      <button type="button" id="sebook-search-clear" class="sebook-search-clear" aria-label="Clear search" hidden="">
2279        <span aria-hidden="true">×</span>
2280      </button>
2281    </div>
2282    <p id="sebook-search-hint" class="sebook-search-hint">
2283      Results filter in real time as you type. Matches are case-insensitive.
2284    </p>
2285    <p id="sebook-search-summary" class="sebook-search-summary" role="status" aria-l
2285ive="polite" aria-atomic="true"></p>
2286  </div>
2287
2288  
2289
2290  <ul id="sebook-search-results" class="sebook-search-results" aria-label="Section and tutorial titles">
2291    
2292      <li class="sebook-search-result sebook-search-result--topic" data-search-title="requirements">
2293        <a href="/SEBook/requirements.html" class="sebook-search-result-link">
2294          <span class="sebook-search-result-title">Requirements</span>
2295          <span class="sebook-search-result-kind">Section</span>
2296        </a>
2297      </li>
2298      
2299        
2300          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="user stories">
2301            <a href="/SEBook/userstories.html" class="sebook-search-result-link">
2302              <span class="sebook-search-result-title">User Stories</span>
2303              <span class="sebook-search-result-kind">Requirements</span>
2304            </a>
2305          </li>
2306          
2307        
2308      
2309    
2310      <li class="sebook-search-result sebook-search-result--topic" data-search-title="design patterns">
2311        <a href="/SEBook/designpatterns.html" class="sebook-search-result-link">
2312          <span class="sebook-search-result-title">Design Patterns</span>
2313          <span class="sebook-search-result-kind">Section</span>
2314        </a>
2315      </li>
2316      
2317        
2318          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="strategy">
2319            <a href="/SEBook/designpatterns/strategy.html" class="sebook-search-result-link">
2320              <span class="sebook-search-result-title">Strategy</span>
2321              <span class="sebook-search-result-kind">Design Patterns</span>
2322            </a>
2323          </li>
2324          
2325        
2326          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="observer">
2327            <a href="/SEBook/designpatterns/observer.html" class="sebook-search-result-link">
2328              <span class="sebook-search-result-title">Observer</span>
2329              <span class="sebook-search-result-kind">Design Patterns</span>
2330            </a>
2331          </li>
2332          
2333        
2334          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="command">
2335            <a href="/SEBook/designpatterns/command.html" class="sebook-search-result-link">
2336              <span class="sebook-search-result-title">Command</span>
2337              <span class="sebook-search-result-kind">Design Patterns</span>
2338            </a>
2339          </li>
2340          
2341        
2342          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="factory method">
2343            <a href="/SEBook/designpatterns/factory_method.html" class="sebook-search-result-link">
2344              <span class="sebook-search-result-title">Factory Method</span>
2345              <span class="sebook-search-result-kind">Design Patterns</span>
2346            </a>
2347          </li>
2348          
2349        
2350          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="abstract factory">
2351            <a href="/SEBook/designpatterns/abstract_factory.html" class="sebook-search-result-link">
2352              <span class="sebook-search-result-title">Abstract Factory</span>
2353              <span class="sebook-search-result-kind">Design Patterns</span>
2354            </a>
2355          </li>
2356          
2357        
2358          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="builder">
2359            <a href="/SEBook/designpatterns/builder.html" class="sebook-search-result-link">
2360              <span class="sebook-search-result-title">Builder</span>
2361              <span class="sebook-search-result-kind">Design Patterns</span>
2362            </a>
2363          </li>
2364          
2365        
2366          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="composite">
2367            <a href="/SEBook/designpatterns/composite.html" class="sebook-search-result-link">
2368              <span class="sebook-search-result-title">Composite</span>
2369              <span class="sebook-search-result-kind">Design Patterns</span>
2370            </a>
2371          </li>
2372          
2373        
2374          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="state">
2375            <a href="/SEBook/designpatterns/state.html" class="sebook-search-result-link">
2376              <span class="sebook-search-result-title">State</span>
2377              <span class="sebook-search-result-kind">Design Patterns</span>
2378            </a>
2379          </li>
2380          
2381        
2382          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="adapter">
2383            <a href="/SEBook/designpatterns/adapter.html" class="sebook-search-result-link">
2384              <span class="sebook-search-result-title">Adapter</span>
2385              <span class="sebook-search-result-kind">Design Patterns</span>
2386            </a>
2387          </li>
2388          
2389        
2390          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="singleton">
2391            <a href="/SEBook/designpatterns/singleton.html" class="sebook-search-result-link">
2392              <span class="sebook-search-result-title">Singleton</span>
2393              <span class="sebook-search-result-kind">Design Patterns</span>
2394            </a>
2395          </li>
2396          
2397        
2398          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="mediator">
2399            <a href="/SEBook/designpatterns/mediator.html" class="sebook-search-result-link">
2400              <span class="sebook-search-result-title">Mediator</span>
2401              <span class="sebook-search-result-kind">Design Patterns</span>
2402            </a>
2403          </li>
2404          
2405        
2406          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="visitor">
2407            <a href="/SEBook/designpatterns/visitor.html" class="sebook-search-result-link">
2408              <span class="sebook-search-result-title">Visitor</span>
2409              <span class="sebook-search-result-kind">Design Patterns</span>
2410            </a>
2411          </li>
2412          
2413        
2414          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="facade">
2415            <a href="/SEBook/designpatterns/facade.html" class="sebook-search-result-link">
2416              <span class="sebook-search-result-title">Facade</span>
2417              <span class="sebook-search-result-kind">Design Patterns</span>
2418            </a>
2419          </li>
2420          
2421        
2422          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="model-view-controller (mvc)">
2423            <a href="/SEBook/designpatterns/mvc.html" class="sebook-search-result-link">
2424              <span class="sebook-search-result-title">Model-View-Controller (MVC)</span>
2425              <span class="sebook-search-result-kind">Design Patterns</span>
2426            </a>
2427          </li>
2428          
2429        
2430      
2431    
2432      <li class="sebook-search-result sebook-search-result--topic" data-search-title="design principles">
2433        <a href="/SEBook/designprinciples/index.html" class="sebook-search-result-link">
2434          <span class="sebook-search-result-title">Design Principles</span>
2435          <span class="sebook-search-result-kind">Section</span>
2436        </a>
2437      </li>
2438      
2439        
2440          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="separation of concerns">
2441            <a href="/SEBook/designprinciples/soc.html" class="sebook-search-result-link">
2442              <span class="sebook-search-result-title">Separation of Concerns</span>
2443              <span class="sebook-search-result-kind">Design Principles</span>
2444            </a>
2445          </li>
2446          
2447        
2448          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="information hiding">
2449            <a href="/SEBook/designprinciples/informationhiding.html" class="sebook-search-result-link">
2450              <span class="sebook-search-result-title">Information Hiding</span>
2451              <span class="sebook-search-result-kind">Design Principles</span>
2452            </a>
2453          </li>
2454          
2455        
2456          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="solid">
2457            <a href="/SEBook/designprinciples/solid.html" class="sebook-search-result-link">
2458              <span class="sebook-search-result-title">SOLID</span>
2459              <span class="sebook-search-result-kind">Design Principles</span>
2460            </a>
2461          </li>
2462          
2463        
2464          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="design with reuse">
2465            <a href="/SEBook/designprinciples/reuse.html" class="sebook-search-result-link">
2466              <span class="sebook-search-result-title">Design with Reuse</span>
2467              <span class="sebook-search-result-kind">Design Principles</span>
2468            </a>
2469          </li>
2470          
2471        
2472      
2473    
2474      <li class="sebook-search-result sebook-search-result--topic" data-search-title="software architecture">
2475        <a href="/SEBook/software_architecture.html" class="sebook-search-result-link">
2476          <span class="sebook-search-result-title">Software Architecture</span>
2477          <span class="sebook-search-result-kind">Section</span>
2478        </a>
2479      </li>
2480      
2481        
2482          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="quality attributes">
2483            <a href="/SEBook/quality_attributes.html" class="sebook-search-result-link">
2484              <span class="sebook-search-result-title">Quality Attributes</span>
2485              <span class="sebook-search-result-kind">Software Architecture</span>
2486            </a>
2487          </li>
2488          
2489            
2490              <li class="sebook-search-result sebook-search-result--item" data-search-title="interoperability">
2491                <a href="/SEBook/quality_attributes/interoperability.html" class="sebook-search-result-link">
2492                  <span class="sebook-search-result-title">Interoperability</span>
2493                  <span class="sebook-search-result-kind">Software Architecture › Quality Attributes</span>
2494                </a>
2495              </li>
2496            
2497              <li class="sebook-search-result sebook-search-result--item" data-search-title="testability">
2498                <a href="/SEBook/quality_attributes/testability.html" class="sebook-search-result-link">
2499                  <span class="sebook-search-result-title">Testability</span>
2500                  <span class="sebook-search-result-kind">Software Architecture › Quality Attributes</span>
2501                </a>
2502              </li>
2503            
2504          
2505        
2506          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="architectural tactics">
2507            <a href="/SEBook/architectural_tactics.html" class="sebook-search-result-link">
2508              <span class="sebook-search-result-title">Architectural Tactics</span>
2509              <span class="sebook-search-result-kind">Software Architecture</span>
2510            </a>
2511          </li>
2512          
2513        
2514          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="architectural styles">
2515            <a href="/SEBook/architectural_styles/index.html" class="sebook-search-result-link">
2516              <span class="sebook-search-result-title">Architectural Styles</span>
2517              <span class="sebook-search-result-kind">Software Architecture</span>
2518            </a>
2519          </li>
2520          
2521            
2522              <li class="sebook-search-result sebook-search-result--item" data-search-title="layered style">
2523                <a href="/SEBook/architectural_styles/layers.html" class="sebook-search-result-link">
2524                  <span class="sebook-search-result-title">Layered Style</span>
2525                  <span class="sebook-search-result-kind">Software Architecture › Architectural Styles</span>
2526                </a>
2527              </li>
2528            
2529              <li class="sebook-search-result sebook-search-result--item" data-search-title="pipes and filters">
2530                <a href="/SEBook/architectural_styles/pipes_and_filters.html" class="sebook-search-result-link">
2531                  <span class="sebook-search-result-title">Pipes and Filters</span>
2532                  <span class="sebook-search-result-kind">Software Architecture › Architectural Styles</span>
2533                </a>
2534              </li>
2535            
2536              <li class="sebook-search-result sebook-search-result--item" data-search-title="publish subscribe">
2537                <a href="/SEBook/architectural_styles/pubsub.html" class="sebook-search-result-link">
2538                  <span class="sebook-search-result-title">Publish Subscribe</span>
2539                  <span class="sebook-search-result-kind">Software Architecture › Architectural Styles</span>
2540                </a>
2541              </li>
2542            
2543          
2544        
2545      
2546    
2547      <li class="sebook-search-result sebook-search-result--topic" data-search-title="software process">
2548        <a href="/SEBook/process.html" class="sebook-search-result-link">
2549          <span class="sebook-search-result-title">Software Process</span>
2550          <span class="sebook-search-result-kind">Section</span>
2551        </a>
2552      </li>
2553      
2554        
2555          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="scrum">
2556            <a href="/SEBook/process/scrum.html" class="sebook-search-result-link">
2557              <span class="sebook-search-result-title">Scrum</span>
2558              <span class="sebook-search-result-kind">Software Process</span>
2559            </a>
2560          </li>
2561          
2562        
2563          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="extreme programming (xp)">
2564            <a href="/SEBook/process/xp.html" class="sebook-search-result-link">
2565              <span class="sebook-search-result-title">Extreme Programming (XP)</span>
2566              <span class="sebook-search-result-kind">Software Process</span>
2567            </a>
2568          </li>
2569          
2570        
2571          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="people and processes">
2572            <a href="/SEBook/process/people-and-processes.html" class="sebook-search-result-link">
2573              <span class="sebook-search-result-title">People and Processes</span>
2574              <span class="sebook-search-result-kind">Software Process</span>
2575            </a>
2576          </li>
2577          
2578        
2579      
2580    
2581      <li class="sebook-search-result sebook-search-result--topic" data-search-title="testing">
2582        <a href="/SEBook/testing.html" class="sebook-search-result-link">
2583          <span class="sebook-search-result-title">Testing</span>
2584          <span class="sebook-search-result-kind">Section</span>
2585        </a>
2586      </li>
2587      
2588        
2589          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="test quality">
2590            <a href="/SEBook/testing/testquality.html" class="sebook-search-result-link">
2591              <span class="sebook-search-result-title">Test Quality</span>
2592              <span class="sebook-search-result-kind">Testing</span>
2593            </a>
2594          </li>
2595          
2596        
2597          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="writing good tests">
2598            <a href="/SEBook/testing/goodtests.html" class="sebook-search-result-link">
2599              <span class="sebook-search-result-title">Writing Good Tests</span>
2600              <span class="sebook-search-result-kind">Testing</span>
2601            </a>
2602          </li>
2603          
2604        
2605          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="testing foundations tutorial">
2606            <a href="/SEBook/testing/testing-foundations-tutorial.html" class="sebook-search-result-link">
2607              <span class="sebook-search-result-title">Testing Foundations Tutorial</span>
2608              <span class="sebook-search-result-kind">Testing</span>
2609            </a>
2610          </li>
2611          
2612        
2613          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="test-driven development (tdd)">
2614            <a href="/SEBook/testing/tdd.html" class="sebook-search-result-link">
2615              <span class="sebook-search-result-title">Test-Driven Development (TDD)</span>
2616              <span class="sebook-search-result-kind">Testing</span>
2617            </a>
2618          </li>
2619          
2620        
2621          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="tdd tutorial">
2622            <a href="/SEBook/testing/tdd-tutorial.html" class="sebook-search-result-link">
2623              <span class="sebook-search-result-title">TDD Tutorial</span>
2624              <span class="sebook-search-result-kind">Testing</span>
2625            </a>
2626          </li>
2627          
2628        
2629          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="test doubles">
2630            <a href="/SEBook/testing/testdoubles.html" class="sebook-search-result-link">
2631              <span class="sebook-search-result-title">Test Doubles</span>
2632              <span class="sebook-search-result-kind">Testing</span>
2633            </a>
2634          </li>
2635          
2636        
2637          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="test doubles tutorial">
2638            <a href="/SEBook/testing/test-doubles-tutorial.html" class="sebook-search-result-link">
2639              <span class="sebook-search-result-title">Test Doubles Tutorial</span>
2640              <span class="sebook-search-result-kind">Testing</span>
2641            </a>
2642          </li>
2643          
2644        
2645      
2646    
2647      <li class="sebook-search-result sebook-search-result--topic" data-search-title="uml">
2648        <a href="/SEBook/uml.html" class="sebook-search-result-link">
2649          <span class="sebook-search-result-title">UML</span>
2650          <span class="sebook-search-result-kind">Section</span>
2651        </a>
2652      </li>
2653      
2654        
2655          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="uml editor">
2656            <a href="/SEBook/tools/uml-editor.html" class="sebook-search-result-link">
2657              <span class="sebook-search-result-title">UML Editor</span>
2658              <span class="sebook-search-result-kind">UML</span>
2659            </a>
2660          </li>
2661          
2662        
2663          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="use case diagrams">
2664            <a href="/SEBook/uml_use_case_diagram.html" class="sebook-search-result-link">
2665              <span class="sebook-search-result-title">Use Case Diagrams</span>
2666              <span class="sebook-search-result-kind">UML</span>
2667            </a>
2668          </li>
2669          
2670        
2671          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="class diagrams">
2672            <a href="/SEBook/uml_class_diagram.html" class="sebook-search-result-link">
2673              <span class="sebook-search-result-title">Class Diagrams</span>
2674              <span class="sebook-search-result-kind">UML</span>
2675            </a>
2676          </li>
2677          
2678        
2679          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="sequence diagrams">
2680            <a href="/SEBook/uml_sequence_diagram.html" class="sebook-search-result-link">
2681              <span class="sebook-search-result-title">Sequence Diagrams</span>
2682              <span class="sebook-search-result-kind">UML</span>
2683            </a>
2684          </li>
2685          
2686        
2687          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="state machine diagrams">
2688            <a href="/SEBook/uml_state_diagram.html" class="sebook-search-result-link">
2689              <span class="sebook-search-result-title">State Machine Diagrams</span>
2690              <span class="sebook-search-result-kind">UML</span>
2691            </a>
2692          </li>
2693          
2694        
2695          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="component diagrams">
2696            <a href="/SEBook/uml_component_diagram.html" class="sebook-search-result-link">
2697              <span class="sebook-search-result-title">Component Diagrams</span>
2698              <span class="sebook-search-result-kind">UML</span>
2699            </a>
2700          </li>
2701          
2702        
2703      
2704    
2705      <li class="sebook-search-result sebook-search-result--topic" data-search-title="development practices">
2706        <a href="/SEBook/development_practices/index.html" class="sebook-search-result-link">
2707          <span class="sebook-search-result-title">Development Practices</span>
2708          <span class="sebook-search-result-kind">Section</span>
2709        </a>
2710      </li>
2711      
2712        
2713          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="beacons">
2714            <a href="/SEBook/development_practices/beacons.html" class="sebook-search-result-link">
2715              <span class="sebook-search-result-title">Beacons</span>
2716              <span class="sebook-search-result-kind">Development Practices</span>
2717            </a>
2718          </li>
2719          
2720        
2721          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="code comprehension">
2722            <a href="/SEBook/development_practices/code_comprehension.html" class="sebook-search-result-link">
2723              <span class="sebook-search-result-title">Code Comprehension</span>
2724              <span class="sebook-search-result-kind">Development Practices</span>
2725            </a>
2726          </li>
2727          
2728        
2729          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="debugging">
2730            <a href="/SEBook/development_practices/debugging.html" class="sebook-search-result-link">
2731              <span class="sebook-search-result-title">Debugging</span>
2732              <span class="sebook-search-result-kind">Development Practices</span>
2733            </a>
2734          </li>
2735          
2736        
2737          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="python debugging tutorial">
2738            <a href="/SEBook/tools/python-debugging.html" class="sebook-search-result-link">
2739              <span class="sebook-search-result-title">Python Debugging Tutorial</span>
2740              <span class="sebook-search-result-kind">Development Practices</span>
2741            </a>
2742          </li>
2743          
2744        
2745          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="gen ai">
2746            <a href="/SEBook/development_practices/genAI.html" class="sebook-search-result-link">
2747              <span class="sebook-search-result-title">Gen Ai</span>
2748              <span class="sebook-search-result-kind">Development Practices</span>
2749            </a>
2750          </li>
2751          
2752        
2753          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="modern code review">
2754            <a href="/SEBook/development_practices/modern_code_review.html" class="sebook-search-result-link">
2755              <span class="sebook-search-result-title">Modern Code Review</span>
2756              <span class="sebook-search-result-kind">Development Practices</span>
2757            </a>
2758          </li>
2759          
2760        
2761          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="prompt engineering">
2762            <a href="/SEBook/development_practices/promptengineering.html" class="sebook-search-result-link">
2763              <span class="sebook-search-result-title">Prompt Engineering</span>
2764              <span class="sebook-search-result-kind">Development Practices</span>
2765            </a>
2766          </li>
2767          
2768        
2769          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="code smells">
2770            <a href="/SEBook/development_practices/code_smells.html" class="sebook-search-result-link">
2771              <span class="sebook-search-result-title">Code Smells</span>
2772              <span class="sebook-search-result-kind">Development Practices</span>
2773            </a>
2774          </li>
2775          
2776        
2777          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="refactoring">
2778            <a href="/SEBook/development_practices/refactoring.html" class="sebook-search-result-link">
2779              <span class="sebook-search-result-title">Refactoring</span>
2780              <span class="sebook-search-result-kind">Development Practices</span>
2781            </a>
2782          </li>
2783          
2784        
2785          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="code smells &amp; refactoring tutorial">
2786            <a href="/SEBook/tools/code-smells-refactoring-tutorial.html" class="sebook-search-result-link">
2787              <span class="sebook-search-result-title">Code Smells &amp; Refactoring Tutorial</span>
2788              <span class="sebook-search-result-kind">Development Practices</span>
2789            </a>
2790          </li>
2791          
2792        
2793          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="top down code comprehension">
2794            <a href="/SEBook/development_practices/topdown.html" class="sebook-search-result-link">
2795              <span class="sebook-search-result-title">Top Down Code Comprehension</span>
2796              <span class="sebook-search-result-kind">Development Practices</span>
2797            </a>
2798          </li>
2799          
2800        
2801      
2802    
2803      <li class="sebook-search-result sebook-search-result--topic" data-search-title="tools">
2804        <a href="/SEBook/tools/index.html" class="sebook-search-result-link">
2805          <span class="sebook-search-result-title">Tools</span>
2806          <span class="sebook-search-result-kind">Section</span>
2807        </a>
2808      </li>
2809      
2810        
2811          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="shell scripting">
2812            <a href="/SEBook/tools/shell.html" class="sebook-search-result-link">
2813              <span class="sebook-search-result-title">Shell Scripting</span>
2814              <span class="sebook-search-result-kind">Tools</span>
2815            </a>
2816          </li>
2817          
2818        
2819          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="shell scripting tutorial">
2820            <a href="/SEBook/tools/shell-tutorial.html" class="sebook-search-result-link">
2821              <span class="sebook-search-result-title">Shell Scripting Tutorial</span>
2822              <span class="sebook-search-result-kind">Tools</span>
2823            </a>
2824          </li>
2825          
2826        
2827          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="regular expressions">
2828            <a href="/SEBook/tools/regex.html" class="sebook-search-result-link">
2829              <span class="sebook-search-result-title">Regular Expressions</span>
2830              <span class="sebook-search-result-kind">Tools</span>
2831            </a>
2832          </li>
2833          
2834        
2835          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="python regex simulator &amp; debugger">
2836            <a href="/SEBook/tools/regex-simulator.html" class="sebook-search-result-link">
2837              <span class="sebook-search-result-title">Python RegEx Simulator &amp; Debugger</span>
2838              <span class="sebook-search-result-kind">Tools</span>
2839            </a>
2840          </li>
2841          
2842        
2843          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="regex tutorial: basics">
2844            <a href="/SEBook/tools/regex-tutorial.html" class="sebook-search-result-link">
2845              <span class="sebook-search-result-title">RegEx Tutorial: Basics</span>
2846              <span class="sebook-search-result-kind">Tools</span>
2847            </a>
2848          </li>
2849          
2850        
2851          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="regex tutorial: advanced">
2852            <a href="/SEBook/tools/regex-tutorial-advanced.html" class="sebook-search-result-link">
2853              <span class="sebook-search-result-title">RegEx Tutorial: Advanced</span>
2854              <span class="sebook-search-result-kind">Tools</span>
2855            </a>
2856          </li>
2857          
2858        
2859          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="python">
2860            <a href="/SEBook/tools/python.html" class="sebook-search-result-link">
2861              <span class="sebook-search-result-title">Python</span>
2862              <span class="sebook-search-result-kind">Tools</span>
2863            </a>
2864          </li>
2865          
2866        
2867          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="python tutorial">
2868            <a href="/SEBook/tools/python-tutorial.html" class="sebook-search-result-link">
2869              <span class="sebook-search-result-title">Python Tutorial</span>
2870              <span class="sebook-search-result-kind">Tools</span>
2871            </a>
2872          </li>
2873          
2874        
2875          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="haskell">
2876            <a href="/SEBook/tools/haskell.html" class="sebook-search-result-link">
2877              <span class="sebook-search-result-title">Haskell</span>
2878              <span class="sebook-search-result-kind">Tools</span>
2879            </a>
2880          </li>
2881          
2882        
2883          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="node.js">
2884            <a href="/SEBook/tools/nodejs.html" class="sebook-search-result-link">
2885              <span class="sebook-search-result-title">Node.js</span>
2886              <span class="sebook-search-result-kind">Tools</span>
2887            </a>
2888          </li>
2889          
2890        
2891          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="node.js tutorial">
2892            <a href="/SEBook/tools/nodejs-tutorial.html" class="sebook-search-result-link">
2893              <span class="sebook-search-result-title">Node.js Tutorial</span>
2894              <span class="sebook-search-result-kind">Tools</span>
2895            </a>
2896          </li>
2897          
2898        
2899          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="react">
2900            <a href="/SEBook/tools/react.html" class="sebook-search-result-link">
2901              <span class="sebook-search-result-title">React</span>
2902              <span class="sebook-search-result-kind">Tools</span>
2903            </a>
2904          </li>
2905          
2906        
2907          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="react tutorial">
2908            <a href="/SEBook/tools/react-tutorial.html" class="sebook-search-result-link">
2909              <span class="sebook-search-result-title">React Tutorial</span>
2910              <span class="sebook-search-result-kind">Tools</span>
2911            </a>
2912          </li>
2913          
2914        
2915          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="git">
2916            <a href="/SEBook/tools/git.html" class="sebook-search-result-link">
2917              <span class="sebook-search-result-title">Git</span>
2918              <span class="sebook-search-result-kind">Tools</span>
2919            </a>
2920          </li>
2921          
2922        
2923          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="git tutorial">
2924            <a href="/SEBook/tools/git-tutorial.html" class="sebook-search-result-link">
2925              <span class="sebook-search-result-title">Git Tutorial</span>
2926              <span class="sebook-search-result-kind">Tools</span>
2927            </a>
2928          </li>
2929          
2930        
2931          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="java">
2932            <a href="/SEBook/tools/java.html" class="sebook-search-result-link">
2933              <span class="sebook-search-result-title">Java</span>
2934              <span class="sebook-search-result-kind">Tools</span>
2935            </a>
2936          </li>
2937          
2938        
2939          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="java tutorial">
2940            <a href="/SEBook/tools/java-tutorial.html" class="sebook-search-result-link">
2941              <span class="sebook-search-result-title">Java Tutorial</span>
2942              <span class="sebook-search-result-kind">Tools</span>
2943            </a>
2944          </li>
2945          
2946        
2947          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="java concepts for cs131">
2948            <a href="/SEBook/tools/java-cs131-tutorial" class="sebook-search-result-link">
2949              <span class="sebook-search-result-title">Java Concepts for CS131</span>
2950              <span class="sebook-search-result-kind">Tools</span>
2951            </a>
2952          </li>
2953          
2954        
2955          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="c programming">
2956            <a href="/SEBook/tools/c.html" class="sebook-search-result-link">
2957              <span class="sebook-search-result-title">C Programming</span>
2958              <span class="sebook-search-result-kind">Tools</span>
2959            </a>
2960          </li>
2961          
2962        
2963          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="c for c++ programmers tutorial">
2964            <a href="/SEBook/tools/c-tutorial.html" class="sebook-search-result-link">
2965              <span class="sebook-search-result-title">C for C++ Programmers Tutorial</span>
2966              <span class="sebook-search-result-kind">Tools</span>
2967            </a>
2968          </li>
2969          
2970        
2971          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="make">
2972            <a href="/SEBook/tools/make.html" class="sebook-search-result-link">
2973              <span class="sebook-search-result-title">Make</span>
2974              <span class="sebook-search-result-kind">Tools</span>
2975            </a>
2976          </li>
2977          
2978        
2979          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="makefile tutorial">
2980            <a href="/SEBook/tools/makefile-tutorial.html" class="sebook-search-result-link">
2981              <span class="sebook-search-result-title">Makefile Tutorial</span>
2982              <span class="sebook-search-result-kind">Tools</span>
2983            </a>
2984          </li>
2985          
2986        
2987          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="playwright tutorial">
2988            <a href="/SEBook/tools/playwright-tutorial.html" class="sebook-search-result-link">
2989              <span class="sebook-search-result-title">Playwright Tutorial</span>
2990              <span class="sebook-search-result-kind">Tools</span>
2991            </a>
2992          </li>
2993          
2994        
2995      
2996    
2997      <li class="sebook-search-result sebook-search-result--topic" data-search-title="systems">
2998        <a href="/SEBook/systems/index.html" class="sebook-search-result-link">
2999          <span class="sebook-search-result-title">Systems</span>
3000          <span class="sebook-search-result-kind">Section</span>
3001        </a>
3002      </li>
3003      
3004        
3005          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="networking">
3006            <a href="/SEBook/tools/networking.html" class="sebook-search-result-link">
3007              <span class="sebook-search-result-title">Networking</span>
3008              <span class="sebook-search-result-kind">Systems</span>
3009            </a>
3010          </li>
3011          
3012        
3013          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="data management">
3014            <a href="/SEBook/systems/data_management.html" class="sebook-search-result-link">
3015              <span class="sebook-search-result-title">Data Management</span>
3016              <span class="sebook-search-result-kind">Systems</span>
3017            </a>
3018          </li>
3019          
3020        
3021          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="security and authentication">
3022            <a href="/SEBook/systems/security.html" class="sebook-search-result-link">
3023              <span class="sebook-search-result-title">Security and Authentication</span>
3024              <span class="sebook-search-result-kind">Systems</span>
3025            </a>
3026          </li>
3027          
3028        
3029      
3030    
3031      <li class="sebook-search-result sebook-search-result--topic" data-search-title="se gym">
3032        <a href="/se-gym/" class="sebook-search-result-link">
3033          <span class="sebook-search-result-title">SE Gym</span>
3034          <span class="sebook-search-result-kind">Section</span>
3035        </a>
3036      </li>
3037      
3038    
3039      <li class="sebook-search-result sebook-search-result--topic" data-search-title="bookmarks">
3040        <a href="/SEBook/bookmarks.html" class="sebook-search-result-link">
3041          <span class="sebook-search-result-title">Bookmarks</span>
3042          <span class="sebook-search-result-kind">Section</span>
3043        </a>
3044      </li>
3045      
3046        
3047          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="cs 35l bookmarks">
3048            <a href="/SEBook/CS35L_bookmarks.html" class="sebook-search-result-link">
3049              <span class="sebook-search-result-title">CS 35L Bookmarks</span>
3050              <span class="sebook-search-result-kind">Bookmarks</span>
3051            </a>
3052          </li>
3053          
3054        
3055          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="cs 130 bookmarks">
3056            <a href="/SEBook/CS130_bookmarks.html" class="sebook-search-result-link">
3057              <span class="sebook-search-result-title">CS 130 Bookmarks</span>
3058              <span class="sebook-search-result-kind">Bookmarks</span>
3059            </a>
3060          </li>
3061          
3062        
3063          <li class="sebook-search-result sebook-search-result--subtopic" data-search-title="cs 131 bookmarks">
3064            <a href="/SEBook/CS131_bookmarks.html" class="sebook-search-result-link">
3065              <span class="sebook-search-result-title">CS 131 Bookmarks</span>
3066              <span class="sebook-search-result-kind">Bookmarks</span>
3067            </a>
3068          </li>
3069          
3070        
3071      
3072    
3073  </ul>
3074
3075  <p id="sebook-search-no-results" class="sebook-search-no-results" hidden="">
3076    No results found.
3077  </p>
3078</section>
3079
3080<h2 id="interactive-tutorials">Interactive Tutorials</h2>
3081<p>The SE Book includes a broad set of interactive tutorials that run directly in your browser, with no installation required.
3082Depending on the topic, you can practice Linux shell scripting in a real Linux <abbr title="Virtual Machine" data-no-tooltip="true">VM</abbr>, explore live <abbr title="Unified Modeling Language" data-no-tooltip="true">UML</abbr> visualizations of your code, step through programs with a time-travel debugger, inspect Git history through an interactive graph, and work through advanced testing concepts.
3083Browse the <a href="/SEBook/tutorials">full list of tutorials</a>.</p>
3084
3085<h2 id="work-in-progress">Work in Progress</h2>
3086<p>Many topics are still a work in progress. 
3087Please consider only the pages linked in your specific course page and already covered in the lecture as “canon”.</p>
3088
3089<h2 id="practice">Practice</h2>
3090<p>To reinforce the concepts from this book, practice regularly in the <a href="/se-gym">SE Gym</a>.</p>
3091
3092<script>
3093(function () {
3094  'use strict';
3095
3096  function init() {
3097    var input = document.getElementById('sebook-search-input');
3098    var clearBtn = document.getElementById('sebook-search-clear');
3099    var resultsList = document.getElementById('sebook-search-results');
3100    var noResults = document.getElementById('sebook-search-no-results');
3101    var summary = document.getElementById('sebook-search-summary');
3102    if (!input || !resultsList || !noResults || !summary) return;
3103
3104    var items = Array.prototype.slice.call(
3105      resultsList.querySelectorAll('.sebook-search-result')
3106    );
3107    var totalCount = items.length;
3108
3109    function setSummary(text) {
3110      if (summary.textContent !== text) summary.textContent = text;
3111    }
3112
3113    function filter(rawQuery) {
3114      var query = (rawQuery || '').trim().toLowerCase();
3115      var visible = 0;
3116      for (var i = 0; i < items.length; i++) {
3117        var title = items[i].getAttribute('data-search-title') || '';
3118        var match = query === '' || title.indexOf(query) !== -1;
3119        items[i].hidden = !match;
3120        if (match) visible++;
3121      }
3122
3123      if (query === '') {
3124        resultsList.hidden = false;
3125        noResults.hidden = true;
3126        setSummary('Showing all ' + totalCount + ' titles.');
3127      } else if (visible === 0) {
3128        resultsList.hidden = true;
3129        noResults.hidden = false;
3130        setSummary('No results found for "' + rawQuery + '".');
3131      } else {
3132        resultsList.hidden = false;
3133        noResults.hidden = true;
3134        setSummary(
3135          visible === 1
3136            ? '1 title matches "' + rawQuery + '".'
3137            : visible + ' titles match "' + rawQuery + '".'
3138        );
3139      }
3140
3141      if (clearBtn) clearBtn.hidden = query === '';
3142    }
3143
3144    input.addEventListener('input', function () {
3145      filter(this.value);
3146    });
3147
3148    input.addEventListener('keydown', function (event) {
3149      if (event.key === 'Escape' && input.value !== '') {
3150        event.preventDefault();
3151        input.value = '';
3152        filter('');
3153      }
3154    });
3155
3156    if (clearBtn) {
3157      clearBtn.addEventListener('click', function () {
3158        input.value = '';
3159        filter('');
3160        input.focus();
3161      });
3162    }
3163
3164    filter('');
3165  }
3166
3167  if (document.readyState === 'loading') {
3168    document.addEventListener('DOMContentLoaded', init);
3169  } else {
3170    init();
3171  }
3172})();
3173</script>
3173
3174
3175
3176              </section>
3177              
3178              
3179              
3180
3181          </div>
3182
3183
3184          
3185      </main>
3186    </div>
3187  </div>
3188
3189  
3189<script>
3190    (function () {
3191      document.addEventListener('focusin', function (e) {
3192        var target = e.target;
3193        if (!target || !target.matches) return;
3194        if (target.matches('#main-content table a, #main-content table button, #main-content table [tabindex]:not([tabindex="-1"])')) {
3195          target.scrollIntoView({ block: 'nearest', inline: 'nearest' });
3196          return;
3197        }
3198        if (!target.matches('#main-content pre[tabindex], .inline-language-panel pre')) return;
3199        var rect = target.getBoundingClientRect();
3200        if (rect.top < 96 || rect.bottom > window.innerHeight) {
3201          target.scrollIntoView({ block: 'center', inline: 'nearest' });
3202        }
3203      });
3204
3205      var sidebar = document.getElementById('sidebar');
3206      var toggleBtn = document.getElementById('sidebar-toggle');
3207
3208      if (!sidebar || !toggleBtn) return;
3209
3210      function syncToggleState() {
3211        var open = sidebar.classList.contains('open');
3212        var isMobile = window.matchMedia('(max-width: 1100px)').matches;
3213        toggleBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
3214        toggleBtn.setAttribute('aria-label', open ? 'Menu: hide table of contents' : 'Menu: show table of contents');
3215        if (isMobile && !open) {
3216          sidebar.setAttribute('inert', '');
3217          sidebar.setAttribute('aria-hidden', 'true');
3218        } else {
3219          sidebar.removeAttribute('inert');
3220          sidebar.removeAttribute('aria-hidden');
3221        }
3222      }
3223      syncToggleState();
3224
3225      // Toggle sidebar on button click (mobile only)
3226      toggleBtn.addEventListener('click', function (e) {
3227        e.stopPropagation();
3228        sidebar.classList.toggle('open');
3229        syncToggleState();
3230      });
3231
3232      // Close sidebar when clicking outside of it on mobile
3233      document.addEventListener('click', function (e) {
3234        var isMobile = window.matchMedia('(max-width: 768px)').matches;
3235        if (!isMobile) return;
3236        if (!sidebar.classList.contains('open')) return;
3237        if (sidebar.contains(e.target) || e.target === toggleBtn) return;
3238        sidebar.classList.remove('open');
3239        syncToggleState();
3240      });
3241
3242      // Close sidebar when a link inside it is clicked (for better UX on mobile)
3243      sidebar.addEventListener('click', function (e) {
3244        var target = e.target;
3245        if (target.tagName === 'A' || target.closest('a')) {
3246          sidebar.classList.remove('open');
3247          syncToggleState();
3248        }
3249      });
3250
3251      // Esc closes the mobile sidebar (SC 1.4.13 Dismissible)
3252      document.addEventListener('keydown', function (e) {
3253        if ((e.key === 'Escape' || e.keyCode === 27) && sidebar.classList.contains('open')) {
3254          sidebar.classList.remove('open');
3255          syncToggleState();
3256          toggleBtn.focus();
3257        }
3258      });
3259
3260      window.addEventListener('resize', syncToggleState);
3261    })();
3262  </script>
3262
3263
3264  
3264<script>
3265    (function () {
3266      function setCookie(name, value, days) {
3267        const d = new Date();
3268        d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
3269        const expires = "expires=" + d.toUTCString();
3270        document.cookie = name + "=" + value + ";" + expires + ";path=/;SameSite=Lax";
3271      }
3272
3273      function getCookie(name) {
3274        const nameEQ = name + "=";
3275        const ca = document.cookie.split(';');
3276        for (let i = 0; i < ca.length; i++) {
3277          let c = ca[i];
3278          while (c.charAt(0) == ' ') c = c.substring(1, c.length);
3279          if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
3280        }
3281        return null;
3282      }
3283
3284      function initToggles() {
3285        const contentRoot = document.getElementById('main-content') || document.querySelector('article') || document.body;
3286        const highlightToggle = document.getElementById('highlightToggle');
3287        const darkModeToggle = document.getElementById('darkModeToggle');
3288        const readAloudToggle = document.getElementById('readAloudToggle');
3289        const container = document.getElementById('togglesContainer');
3290
3291        if (!darkModeToggle || !container) return;
3292
3293        const marks = contentRoot.getElementsByTagName('mark');
3294        const audioPlayers = contentRoot.getElementsByClassName('cap');
3295        const hasHighlights = highlightToggle && marks.length > 0;
3296        const hasAudioPlayers = readAloudToggle && audioPlayers.length > 0;
3297
3298        function setControlVisible(toggle, visible) {
3299          const row = toggle && toggle.closest('div');
3300          if (row) {
3301            row.style.display = visible ? 'flex' : 'none';
3302          }
3303        }
3304
3305        // Dark mode is always available; page-specific toggles appear only
3306        // when their matching content exists.
3307        container.classList.remove('is-hidden');
3308        container.style.display = 'flex';
3309        setControlVisible(highlightToggle, hasHighlights);
3310
3311        // Audio Clips toggle — only shown when .cap players exist on this page
3312        setControlVisible(readAloudToggle, hasAudioPlayers);
3313
3314        // --- Dark Mode Logic ---
3315        const savedDarkMode = getCookie('dark-mode');
3316        const isDark = savedDarkMode === 'true';
3317        darkModeToggle.checked = isDark;
3318        if (isDark) {
3319          document.documentElement.classList.add('dark-mode');
3320        }
3321
3322        darkModeToggle.addEventListener('change', function () {
3323          document.documentElement.classList.add('dark-mode-transition');
3324          if (this.checked) {
3325            document.documentElement.classList.add('dark-mode');
3326          } else {
3327            document.documentElement.classList.remove('dark-mode');
3328          }
3329          setCookie('dark-mode', this.checked, 300);
3330          setTimeout(() => {
3331            document.documentElement.classList.remove('dark-mode-transition');
3332          }, 300);
3333        });
3334
3335        // --- Highlight Logic ---
3336        if (hasHighlights) {
3337          const savedHighlights = getCookie('show-highlights');
3338          if (savedHighlights !== null) {
3339            const isChecked = savedHighlights === 'true';
3340            highlightToggle.checked = isChecked;
3341            if (isChecked) {
3342              document.documentElement.classList.remove('highlights-disabled');
3343            } else {
3344              document.documentElement.classList.add('highlights-disabled');
3345            }
3346          }
3347
3348          highlightToggle.addEventListener('change', function () {
3349            document.documentElement.classList.add('highlights-transition');
3350            if (this.checked) {
3351              document.documentElement.classList.remove('highlights-disabled');
3352            } else {
3353              document.documentElement.classList.add('highlights-disabled');
3354            }
3355            setCookie('show-highlights', this.checked, 300);
3356            setTimeout(() => {
3357              document.documentElement.classList.remove('highlights-transition');
3358            }, 300);
3359          });
3360        }
3361
3362        // --- Read Aloud Toggle Logic ---
3363        const savedReadAloud = getCookie('read-aloud');
3364        const isReadAloud = savedReadAloud !== 'false'; // Default is true (ON)
3365
3366        if (hasAudioPlayers) {
3367          readAloudToggle.checked = isReadAloud;
3368          if (isReadAloud) {
3369            document.documentElement.classList.add('read-aloud-enabled');
3370          } else {
3371            document.documentElement.classList.remove('read-aloud-enabled');
3372          }
3373
3374          readAloudToggle.addEventListener('change', function () {
3375            if (this.checked) {
3376              document.documentElement.classList.add('read-aloud-enabled');
3377            } else {
3378              document.documentElement.classList.remove('read-aloud-enabled');
3379            }
3380            setCookie('read-aloud', this.checked, 300);
3381          });
3382        }
3383      }
3384
3385      // Run when DOM is ready
3386      if (document.readyState === 'loading') {
3387        document.addEventListener('DOMContentLoaded', initToggles);
3388      } else {
3389        initToggles();
3390      }
3391    })();
3392  </script>
3392
3393
3394  
3395  
3395<script>
3396    (function () {
3397      function initBookmarkBtn() {
3398        if (!window.SEBookmarks || !SEBookmarks.isBookmarksActive()) return;
3399        var wrapper = document.getElementById('bookmarkBtnWrapper');
3400        var btn = document.getElementById('bookmarkPageBtn');
3401        var icon = document.getElementById('bookmarkIcon');
3402        if (!wrapper || !btn || !icon) return;
3403        var url = window.location.pathname;
3404        var title = wrapper.getAttribute('data-page-title') || document.title;
3405        wrapper.classList.remove('is-hidden');
3406        wrapper.style.display = 'flex';
3407        var container = document.getElementById('togglesContainer');
3408        if (container && (container.style.display === 'none' || container.classList.contains('is-hidden'))) {
3409          container.classList.remove('is-hidden');
3410          container.style.display = 'flex';
3411        }
3412        function updateIcon() {
3413          if (SEBookmarks.isBookmarked(url)) {
3414            icon.className = 'fa-solid fa-bookmark';
3415            btn.setAttribute('aria-label', 'Remove bookmark for this page');
3416          } else {
3417            icon.className = 'fa-regular fa-bookmark';
3418            btn.setAttribute('aria-label', 'Bookmark this page');
3419          }
3420        }
3421        updateIcon();
3422        btn.addEventListener('click', function () {
3423          if (SEBookmarks.isBookmarked(url) && !window.confirm('Remove bookmark for this page?')) return;
3424          SEBookmarks.toggleBookmark(url, title);
3425          updateIcon();
3426        });
3427      }
3428      if (document.readyState === 'loading') {
3429        document.addEventListener('DOMContentLoaded', initBookmarkBtn);
3430      } else {
3431        initBookmarkBtn();
3432      }
3433    })();
3434  </script>
3434
3435  
3436
3437  
3437<script>
3438    function adjustNavbarPadding() {
3439      const navbar = document.getElementById('navnav');
3440      const content = document.getElementById('sebook-content-wrapper');
3441      if (navbar && content) {
3442        const height = navbar.offsetHeight;
3443        content.style.marginTop = (height) + 'px';
3444
3445        // Also adjust sidebar toggle position
3446        const toggle = document.getElementById('sidebar-toggle');
3447        if (toggle) {
3448          toggle.style.top = (height - 7) + 'px';
3449        }
3450      }
3451    }
3452
3453    // Run immediately to catch the first paint
3454    adjustNavbarPadding();
3455
3456    window.addEventListener('load', adjustNavbarPadding);
3457    window.addEventListener('resize', adjustNavbarPadding);
3458
3459    let adjustmentCount = 0;
3460    const adjustmentInterval = setInterval(() => {
3461      adjustNavbarPadding();
3462      adjustmentCount++;
3463      if (adjustmentCount > 10) clearInterval(adjustmentInterval);
3464    }, 200);
3465  </script>
3465
3466
3467  
3467<script src="/js/sebook-sidebar-nav.js" defer></script>
3467
3468
3469  <!-- Footer -->
3470<footer>
3471  <div class="col-md-12 text-center">
3472
3473    
3474    <p>
3475      
3476      <a href="https://github.com/tobiasduerschmid" target="_blank" rel="noopener" data-original-title="GitHub" aria-label="GitHub profile (opens in new tab)" class="footer-social-link"><i class="fa-brands fa-github" aria-hidden="true"></i><span class="sr-only">GitHub profile (opens in new tab)</span></a>
3477      
3478      
3479      <a href="https://www.linkedin.com/in/tobias-duerschmid" target="_blank" rel="noopener" data-original-title="LinkedIn" aria-label="LinkedIn profile (opens in new tab)" class="footer-social-link"><i class="fa-brands fa-linkedin" aria-hidden="true"></i><span class="sr-only">LinkedIn profile (opens in new tab)</span></a>
3480      
3481      
3482      <a href="https://twitter.com/TDurschmid" target="_blank" rel="noopener" data-original-title="Twitter/X" aria-label="Twitter/X profile (opens in new tab)" class="footer-social-link"><i class="fa-brands fa-x-twitter" aria-hidden="true"></i><span class="sr-only">Twitter/X profile (opens in new tab)</span></a>
3483      
3484      
3485      <a href="https://scholar.google.com/citations?user=tmE8FjQAAAAJ" target="_blank" rel="noopener" data-original-title="Google Scholar" aria-label="Google Scholar profile (opens in new tab)" class="footer-social-link"><i class="fa-solid fa-graduation-cap" aria-hidden="true"></i><span class="sr-only">Google Scholar profile (opens in new tab)</span></a>
3486      
3487      
3488      <a href="https://orcid.org/0000-0001-8612-1767" target="_blank" rel="noopener" data-original-title="ORCID" aria-label="ORCID profile (opens in new tab)" class="footer-social-link"><i class="fa-brands fa-orcid" aria-hidden="true"></i><span class="sr-only">ORCID profile (opens in new tab)</span></a>
3489      
3490    </p>
3491    
3492
3493    <p class="footer-copy">
3494      <a href="/glossary/">Glossary</a>
3495      &middot;
3496      <a href="/shortcuts/">Keyboard shortcuts</a>
3497      &middot;
3498      <a href="/settings/">My Settings</a>
3499      &middot;
3500      <a href="/cookies/">Browser storage</a>
3501    </p>
3502
3503    <a href="https://github.com/cgcostume/cgcostume.github.io">Datafolio</a> by Tobias Dürschmid: Created using <a href="https://jekyllrb.com/" target="_blank">Jekyll</a> and <a
3504      href="https://getbootstrap.com/" target="_blank">Bootstrap</a>, generated and hosted via <a
3505      href="https://pages.github.com/" target="_blank">gh-pages</a>. Last updated on <a
3506      href="https://github.com/tobiasduerschmid/tobiasduerschmid.github.io/commits/master" target="_blank">10/03/26</a>.
3507
3508    <p class="footer-ai-notice">Tobias Dürschmid expressly reserves the use of this site's content for text and data mining, including training or fine-tuning AI models, pursuant to Article 4(3) of Directive (EU) 2019/790. Any such use requires prior written permission.
3509</p>
3510  </div>
3511</footer>
3512
3513
3514  <!-- Privacy / Cookie Notice -->
3515  <div class="privacy-notice-region" role="region" aria-label="Privacy notice">
3516    
3517
3518<div class="cookie-notice-wrap">
3519  <p class="cookie-notice">
3520    <strong>Cookie &amp; Privacy Notice:</strong>
3521    Saved preferences and progress stay in your browser. This site has no analytics or advertising
3522    trackers. StackBlitz processes workspace files and commands for WebContainer-backed Node.js
3523    tutorials; do not enter secrets or confidential code there.
3524    <a href="/cookies/">View, manage, and learn how data is handled &rarr;</a>
3525  </p>
3526</div>
3527
3528
3529  </div>
3530
3531  <!-- TTS control bar (shown while reading aloud) -->
3532  <div id="tts-bar" class="tts-control-bar" role="region" aria-label="Text-to-speech controls">
3533    <span class="tts-control-label">
3534      <i class="fa fa-volume-up" aria-hidden="true"></i> Reading aloud
3535    </span>
3536    <button id="tts-prev-heading" class="tts-control-button is-square tts-control-hidden" data-original-title="Previous heading" aria-label="Jump to previous heading">
3537      <i class="fa fa-step-backward" aria-hidden="true"></i>
3538    </button>
3539    <button id="tts-back-10s" class="tts-control-button" data-original-title="Back 10 seconds" aria-label="Back 10 seconds">
3540      <i class="fa fa-undo" aria-hidden="true"></i> 10s
3541    </button>
3542    <button id="tts-playpause" class="tts-control-button is-primary" data-original-title="Pause / Resume" aria-label="Pause reading" aria-pressed="true">
3543      <i class="fa fa-pause" aria-hidden="true"></i>
3544    </button>
3545    <button id="tts-fwd-10s" class="tts-control-button" data-original-title="Forward 10 seconds" aria-label="Forward 10 seconds">
3546      10s <i class="fa fa-redo" aria-hidden="true"></i>
3547    </button>
3548    <button id="tts-next-heading" class="tts-control-button is-square tts-control-hidden" data-original-title="Next heading" aria-label="Jump to next heading">
3549      <i class="fa fa-step-forward" aria-hidden="true"></i>
3550    </button>
3551    <button id="tts-slower" class="tts-control-button" data-original-title="Slower">
3552      &#8722; Slower
3553    </button>
3554    <span id="tts-rate" class="tts-control-rate">1.0x</span>
3555    <button id="tts-faster" class="tts-control-button" data-original-title="Faster">
3556      + Faster
3557    </button>
3558    <select id="tts-voice-select" class="tts-control-select" data-original-title="Select voice" aria-label="Select the voice used for reading aloud">
3559      <option value="">Default voice</option>
3560    </select>
3561    <button id="tts-stop" class="tts-control-button is-danger" data-original-title="Stop reading">
3562      <i class="fa fa-stop" aria-hidden="true"></i> Stop
3563    </button>
3564  </div>
3565
3566  
3566<script src="/js/tts-player.js"></script>
3566
3567  
3567<script>
3568    (function () {
3569      var VOICE_KEY = 'tts-voice-name';
3570
3571      function initTTS() {
3572        if (!window.TTSPlayer || !TTSPlayer.isSupported()) {
3573          var btn = document.getElementById('tts-read-btn');
3574          if (btn) btn.style.display = 'none';
3575          return;
3576        }
3577
3578        var readBtn       = document.getElementById('tts-read-btn');
3579        var bar           = document.getElementById('tts-bar');
3580        var playPauseBtn  = document.getElementById('tts-playpause');
3581        var slowerBtn     = document.getElementById('tts-slower');
3582        var fasterBtn     = document.getElementById('tts-faster');
3583        var stopBtn       = document.getElementById('tts-stop');
3584        var rateDisplay   = document.getElementById('tts-rate');
3585        var voiceSel      = document.getElementById('tts-voice-select');
3586        var prevHeadingBtn = document.getElementById('tts-prev-heading');
3587        var nextHeadingBtn = document.getElementById('tts-next-heading');
3588        var back10Btn      = document.getElementById('tts-back-10s');
3589        var fwd10Btn       = document.getElementById('tts-fwd-10s');
3590
3591        if (!readBtn || !bar) return;
3592
3593        // Populate voice selector once voices are available
3594        TTSPlayer.onVoicesReady(function () {
3595          var voices = TTSPlayer.getVoices();
3596          if (!voices.length || !voiceSel) return;
3597
3598          // Group by locale (voices already sorted best-first within each locale)
3599          var locales = {};
3600          voices.forEach(function (item) {
3601            var loc = item.lang;
3602            if (!locales[loc]) locales[loc] = [];
3603            locales[loc].push(item);
3604          });
3605
3606          voiceSel.innerHTML = '<option value="">Default voice</option>';
3607          Object.keys(locales).sort(function (a, b) {
3608            if (/^en-US/i.test(a)) return -1;
3609            if (/^en-US/i.test(b)) return  1;
3610            return a.localeCompare(b);
3611          }
3611).forEach(function (loc) {
3612            var grp = document.createElement('optgroup');
3613            grp.label = loc;
3614            locales[loc].forEach(function (item) {
3615              var opt = document.createElement('option');
3616              opt.value = item.voice.name;
3617              opt.textContent = item.label;
3618              grp.appendChild(opt);
3619            });
3620            voiceSel.appendChild(grp);
3621          });
3622
3623          // Restore saved voice, or auto-select the best-sounding one
3624          var saved = localStorage.getItem(VOICE_KEY);
3625          var activeVoice = null;
3626          if (saved) {
3627            var match = voices.find(function (v) { return v.voice.name === saved; });
3628            if (match) { activeVoice = match; voiceSel.value = saved; }
3629          }
3630          if (!activeVoice) {
3631            var best = TTSPlayer.bestVoice();
3632            if (best) {
3633              activeVoice = best;
3634              voiceSel.value = best.voice.name;
3635              localStorage.setItem(VOICE_KEY, best.voice.name);
3636            }
3637          }
3638          if (activeVoice) TTSPlayer.setVoice(activeVoice.voice);
3639
3640          voiceSel.addEventListener('change', function () {
3641            var name = this.value;
3642            localStorage.setItem(VOICE_KEY, name);
3643            if (!name) { TTSPlayer.setVoice(null); return; }
3644            var found = voices.find(function (v) { return v.voice.name === name; });
3645            if (found) TTSPlayer.setVoice(found.voice);
3646          });
3647        });
3648
3649        function updateBar() {
3650          var speaking = TTSPlayer.isSpeaking();
3651          var paused   = TTSPlayer.isPaused();
3652          bar.style.display = (speaking || paused) ? 'flex' : 'none';
3653          if (playPauseBtn) {
3654            playPauseBtn.innerHTML = paused
3655              ? '<i class="fa fa-play" aria-hidden="true"></i>'
3656              : '<i class="fa fa-pause" aria-hidden="true"></i>';
3657            playPauseBtn.setAttribute('data-original-title', paused ? 'Resume' : 'Pause');
3658            playPauseBtn.removeAttribute('title');
3659            if (window.jQuery && window.jQuery.fn.tooltip) {
3660              window.jQuery(playPauseBtn).tooltip('hide').attr('data-original-title', playPauseBtn.getAttribute('data-original-title'));
3661            }
3662            playPauseBtn.setAttribute('aria-label', paused ? 'Resume reading' : 'Pause reading');
3663            playPauseBtn.setAttribute('aria-pressed', paused ? 'false' : 'true');
3664          }
3665          if (rateDisplay) rateDisplay.textContent = TTSPlayer.rateLabel();
3666          if (!speaking && !paused) {
3667            readBtn.innerHTML = '<i class="fa fa-volume-up tts-read-inline-icon" aria-hidden="true"></i>Read Aloud';
3668            readBtn.style.color = '#2774AE';
3669            readBtn.style.borderColor = '#2774AE';
3670          }
3671        }
3672
3673        readBtn.addEventListener('click', function () {
3674          if (TTSPlayer.isSpeaking() || TTSPlayer.isPaused()) {
3675            TTSPlayer.stop();
3676            return;
3677          }
3678          var content = document.getElementById('main-content');
3679          var extracted = TTSPlayer.extract(content);
3680          if (!extracted.text) return;
3681
3682          readBtn.innerHTML = '<i class="fa fa-stop tts-read-inline-icon" aria-hidden="true"></i>Stop Reading';
3683          readBtn.style.color = '#c0392b';
3684          readBtn.style.borderColor = '#c0392b';
3685          // Show heading-skip buttons only when the page actually has
3686          // multiple headings to skip between.
3687          var hasHeadings = extracted.markers && extracted.markers.length > 1;
3688          if (prevHeadingBtn) prevHeadingBtn.style.display = hasHeadings ? 'flex' : 'none';
3689          if (nextHeadingBtn) nextHeadingBtn.style.display = hasHeadings ? 'flex' : 'none';
3690          TTSPlayer.speak(extracted, { onUpdate: updateBar, onEnd: updateBar });
3691          updateBar();
3692        });
3693
3694        if (playPauseBtn) {
3695          playPauseBtn.addEventListener('click', function () {
3696            TTSPlayer.isPaused() ? TTSPlayer.resume() : TTSPlayer.pause();
3697          });
3698        }
3699        if (slowerBtn) {
3700          slowerBtn.addEventListener('click', function () {
3701            TTSPlayer.setRate(TTSPlayer.getRate() - 0.1);
3702            if (rateDisplay) rateDisplay.textContent = TTSPlayer.rateLabel();
3703          });
3704        }
3705        if (fasterBtn) {
3706          fasterBtn.addEventListener('click', function () {
3707            TTSPlayer.setRate(TTSPlayer.getRate() + 0.1);
3708            if (rateDisplay) rateDisplay.textContent = TTSPlayer.rateLabel();
3709          });
3710        }
3711        if (back10Btn) {
3712          back10Btn.addEventListener('click', function () { TTSPlayer.seekRelative(-10); });
3713        }
3714        if (fwd10Btn) {
3715          fwd10Btn.addEventListener('click', function () { TTSPlayer.seekRelative(10); });
3716        }
3717        if (prevHeadingBtn) {
3718          prevHeadingBtn.addEventListener('click', function () { TTSPlayer.seekToHeading('prev'); });
3719        }
3720        if (nextHeadingBtn) {
3721          nextHeadingBtn.addEventListener('click', function () { TTSPlayer.seekToHeading('next'); });
3722        }
3723        if (stopBtn) {
3724          stopBtn.addEventListener('click', function () { TTSPlayer.stop(); });
3725        }
3726      }
3727
3728      if (document.readyState === 'loading') {
3729        document.addEventListener('DOMContentLoaded', initTTS);
3730      } else {
3731        initTTS();
3732      }
3733    })();
3734  </script>
3734
3735
3736  <!-- Shared inline language switcher for multi-language code samples -->
3737  
3737<script>
3738  (function () {
3739    'use strict';
3740
3741    function optionValue(button) {
3742      return button ? button.getAttribute('data-language-option') : null;
3743    }
3744
3745    function activate(root, language, focusButton) {
3746      var buttons = root.querySelectorAll('[data-language-option]');
3747      var panels = root.querySelectorAll('[data-language-panel]');
3748
3749      for (var i = 0; i < buttons.length; i++) {
3750        var isActiveButton = optionValue(buttons[i]) === language;
3751        buttons[i].setAttribute('aria-selected', isActiveButton ? 'true' : 'false');
3752        buttons[i].setAttribute('tabindex', isActiveButton ? '0' : '-1');
3753        if (isActiveButton && focusButton) buttons[i].focus();
3754      }
3755
3756      for (var j = 0; j < panels.length; j++) {
3757        var isActivePanel = panels[j].getAttribute('data-language-panel') === language;
3758        panels[j].classList.toggle('is-active', isActivePanel);
3759        panels[j].setAttribute('aria-hidden', isActivePanel ? 'false' : 'true');
3760        // Pair aria-hidden with `inert` so focusable content inside an
3761        // inactive panel (notably the Rouge code blocks marked tabindex=0
3762        // by accessibility-fixes.js) is removed from the focus and AT
3763        // tree, satisfying WCAG 4.1.2.
3764        if (isActivePanel) panels[j].removeAttribute('inert');
3765        else panels[j].setAttribute('inert', '');
3766      }
3767    }
3768
3769    function move(root, currentButton, direction) {
3770      var buttons = Array.prototype.slice.call(root.querySelectorAll('[data-language-option]'));
3771      var index = buttons.indexOf(currentButton);
3772      if (index < 0 || buttons.length === 0) return;
3773
3774      var nextIndex = index;
3775      if (direction === 'next') nextIndex = (index + 1) % buttons.length;
3776      if (direction === 'previous') nextIndex = (index - 1 + buttons.length) % buttons.length;
3777      if (direction === 'first') nextIndex = 0;
3778      if (direction === 'last') nextIndex = buttons.length - 1;
3779
3780      activate(root, optionValue(buttons[nextIndex]), true);
3781    }
3782
3783    function initSwitcher(root) {
3784      if (root.getAttribute('data-language-switcher-ready') === 'true') return;
3785      root.setAttribute('data-language-switcher-ready', 'true');
3786
3787      var buttons = root.querySelectorAll('[data-language-option]');
3788      if (buttons.length === 0) return;
3789
3790      for (var i = 0; i < buttons.length; i++) {
3791        buttons[i].addEventListener('click', function () {
3792          activate(root, optionValue(this), false);
3793        });
3794
3795        buttons[i].addEventListener('keydown', function (event) {
3796          var key = event.key || event.keyCode;
3797          if (key === 'ArrowRight' || key === 39) {
3798            event.preventDefault();
3799            move(root, this, 'next');
3800          } else if (key === 'ArrowLeft' || key === 37) {
3801            event.preventDefault();
3802            move(root, this, 'previous');
3803          } else if (key === 'Home' || key === 36) {
3804            event.preventDefault();
3805            move(root, this, 'first');
3806          } else if (key === 'End' || key === 35) {
3807            event.preventDefault();
3808            move(root, this, 'last');
3809          }
3810        });
3811      }
3812
3813      var selected = root.querySelector('[data-language-option][aria-selected="true"]');
3814      var defaultLanguage = root.getAttribute('data-default-language') || optionValue(selected) || optionValue(buttons[0]);
3815      activate(root, defaultLanguage, false);
3816    }
3817
3818    function initAll() {
3819      var roots = document.querySelectorAll('[data-language-switcher]');
3820      for (var i = 0; i < roots.length; i++) initSwitcher(roots[i]);
3821    }
3822
3823    window.SEBookLanguageSwitcher = {
3824      initAll: initAll
3825    };
3826
3827    if (document.readyState === 'loading') {
3828      document.addEventListener('DOMContentLoaded', initAll);
3829    } else {
3830      initAll();
3831    }
3832  })();
3833  </script>
3833
3834
3835  
3836
3837  <!-- Bundled UML diagram renderer -->
3838  
3838<script src="/js/ArchUML/uml-bundle.js" defer></script>
3838
3839  <!-- Verbal aria-label generator (parses the spec for screen-reader text alternatives) -->
3840  
3840<script src="/js/uml-auto-describe.js" defer></script>
3840
3841
3842  <!-- Global UML inline diagram init — renders data-uml-type/data-uml-spec containers
3843       and re-renders on dark mode toggle -->
3844  
3844<script>
3845  (function () {
3846    'use strict';
3847    function renderAll() {
3848      if (window.UMLShared) window.UMLShared.renderAll();
3849    }
3850
3851    function tryRender() {
3852      if (window.UMLClassDiagram && window.UMLSequenceDiagram && window.UMLShared) {
3853        renderAll();
3854      } else {
3855        setTimeout(tryRender, 80);
3856      }
3857    }
3858
3859    new MutationObserver(function (muts) {
3860      for (var i = 0; i < muts.length; i++) {
3861        if (muts[i].attributeName === 'class') { setTimeout(renderAll, 50); return; }
3862      }
3863    }).observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
3864
3865    if (document.readyState === 'loading') {
3866      document.addEventListener('DOMContentLoaded', tryRender);
3867    } else {
3868      tryRender();
3869    }
3870  })();
3871  </script>
3871
3872
3873  <!-- Scripts -->
3874
3875<!-- jQuery -->
3876<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"
3877        integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs"
3878        crossorigin="anonymous"></script>
vendor: 1 bytes, line 3878
3878
3879<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"
3880        integrity="sha384-mE6eXfrb8jxl0rzJDBRanYqgBxtJ6Unn4/1F7q4xRRyIw7Vdg9jP4ycT7x1iVsgb"
3881        crossorigin="anonymous"></script>
vendor: 1 bytes, line 3881
3881
3882<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.1/jquery.validate.min.js"
3883        integrity="sha384-sjPkI5PMV07CLe+7G2T7RoXXuInPfKFXLmXMZVObfN+m/3Lcrho/dVnTy2sxAj+k"
3884        crossorigin="anonymous"></script>
3884
3885
3886<script src="/js/datafolio.js"></script>
3886
3887
3888
3889<!-- Bootstrap Core JavaScript -->
3890<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"
3891        integrity="sha384-4Kp4aQ6UNeqsJ/ithPcxYnnIGt/QJJ64J9QtfDAJZUTaePAIPm9aaBdu7Gw84oGs"
3892        crossorigin="anonymous"></script>
3892
3893
3894<!-- blueimp gallery -->
3895<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"
3896        integrity="sha384-fnia1AW9zazttWcipx8gfp6yPE2+6F3j3TVk5ED3Ywr4zpb15F6uhnsFRPOwBOmQ"
3897        crossorigin="anonymous"></script>
vendor: 1 bytes, line 3897
3897
3898<script src=" /js/bootstrap-image-gallery.min.js"></script>
3898
3899
3900<!-- spin.js -->
3901<script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.0.1/spin.min.js"
3902        integrity="sha384-pFr2CxmL5mdJ+7jdwMuf5BqhupiZDEzBxOcEbo/KLbPYCdiwd0tA3DEJ0KfEAAD4"
3903        crossorigin="anonymous"></script>
vendor: 1 bytes, line 3903
3903
3904<script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.0.1/jquery.spin.min.js"
3905        integrity="sha384-ZcjHw0rCBNClq8TV0QXvC07VnAJl0RSCYqIt1GBnA7wEEWwWqXiq+UMfn9jVVHPw"
3906        crossorigin="anonymous"></script>
3906
3907
3908<!-- clipboard.js -->
3909<script src=" /js/clipboard.min.js"></script>
3909
3910
3911<!-- Scrolling Nav JavaScript -->
3912<script src=" /js/scrolling-nav.js"></script>
3912
3913
3914<!-- More Stuf... -->
3915<!-- 
3915<script src="/js/retina-1.1.0.js"></script>
3915 (removed - 404) -->
3916<script src=" /js/jquery.hoverdir.js"></script>
vendor: 1 bytes, line 3916
3916
3917<script src=" /js/jquery.hoverex.min.js"></script>
vendor: 1 bytes, line 3917
3917
3918<script src=" /js/jquery.isotope.min.js"></script>
vendor: 1 bytes, line 3918
3918
3919<script src=" /js/unslider-min.js"></script>
vendor: 1 bytes, line 3919
3919
3920<script>
3921  $(document).ready(function () {
3922    // Tooltips: manual triggers keep the tooltip hoverable and persistent
3923    // while focus/hover remains, and Esc dismisses without moving focus.
3924    var tooltipSelector = '[data-toggle="tooltip"], [data-original-title], [data-tooltip], [title]:not([data-no-tooltip]):not(iframe)';
3925
3926    function normalizeTooltipTrigger(trigger) {
3927      var $trigger = $(trigger);
3928      var nativeTitle = $trigger.attr('title');
3929      if (nativeTitle && !$trigger.attr('data-original-title')) {
3930        $trigger.attr('data-original-title', nativeTitle);
3931      }
3932      $trigger.removeAttr('title');
3933    }
3934
3935    function clearTooltipTimer($trigger, dataKey) {
3936      var timer = $trigger.data(dataKey);
3937      if (!timer) return;
3938      window.clearTimeout(timer);
3939      $trigger.removeData(dataKey);
3940    }
3941
3942    function clearHideTimer($trigger) {
3943      clearTooltipTimer($trigger, 'a11yTooltipHideTimer');
3944    }
3945
3946    function clearShowTimer($trigger) {
3947      clearTooltipTimer($trigger, 'a11yTooltipShowTimer');
3948    }
3949
3950    function initAccessibleTooltips(selector, options) {
3951      var $triggers = $(selector);
3952      if (!$triggers.length) return;
3953      $triggers.each(function () { normalizeTooltipTrigger(this); });
3954      $triggers.tooltip($.extend({
3955        trigger: 'manual',
3956        delay: 0,
3957        container: 'body',
3958        html: false,
3959        placement: 'auto',
3960        viewport: { selector: 'body', padding: 8 }
3961      }, options || {}));
3962
3963      function getTip($trigger) {
3964        var data = $trigger.data('bs.tooltip');
3965        if (data && data.$tip) return data.$tip;
3966        var id = $trigger.attr('aria-describedby');
3967        return id ? $('#' + id) : $();
3968      }
3969
3970      // :focus-visible isolates genuine keyboard focus. Plain :focus also
3971      // matches buttons that received focus from a mouse click — those buttons
3972      // keep :focus after the cursor moves away, which would otherwise pin the
3973      // tooltip open until the user clicked somewhere else.
3974      function hasKeyboardFocus($trigger) {
3975        try { return $trigger.is(':focus-visible'); }
3976        catch (e) { return false; }
3977      }
3978
3979      function scheduleHide($trigger) {
3980        clearHideTimer($trigger);
3981        var timer = window.setTimeout(function () {
3982          $trigger.removeData('a11yTooltipHideTimer');
3983          var $tip = getTip($trigger);
3984          if ($trigger.is(':hover') || hasKeyboardFocus($trigger) || ($tip.length && $tip.is(':hover'))) {
3985            scheduleHide($trigger);
3986            return;
3987          }
3988          $trigger.tooltip('hide');
3989        }, 150);
3990        $trigger.data('a11yTooltipHideTimer', timer);
3991      }
3992
3993      function showTooltip(trigger) {
3994        var $trigger = $(trigger);
3995        clearHideTimer($trigger);
3996        clearShowTimer($trigger);
3997        $trigger.tooltip('show');
3998        window.setTimeout(function () {
3999          getTip($trigger)
4000            .off('.a11yTooltipHover')
4001            .on('mouseenter.a11yTooltipHover', function () {
4002              clearHideTimer($trigger);
4003            })
4004            .on('mouseleave.a11yTooltipHover', function () {
4005              scheduleHide($trigger);
4006            });
4007        }, 0);
4008      }
4009
4010      // Delay hover-only tooltips so quick cursor travel across dense toolbars
4011      // does not fill the page with boxes. Focus remains immediate for keyboard
4012      // users because it is deliberate navigation, not incidental pointer motion.
4013      var HOVER_SHOW_DELAY = 1000;
4014      function scheduleShow(trigger) {
4015        var $trigger = $(trigger);
4016        clearShowTimer($trigger);
4017        var timer = window.setTimeout(function () {
4018          $trigger.removeData('a11yTooltipShowTimer');
4019          if ($trigger.is(':hover')) showTooltip(trigger);
4020        }, HOVER_SHOW_DELAY);
4021        $trigger.data('a11yTooltipShowTimer', timer);
4022      }
4023
4024      // Touch devices fire `mouseenter` and `focusin` on tap but never the
4025      // matching `mouseleave` / `focusout`, so a tap would pin the tooltip
4026      // open until the next tap somewhere else. Skip the hover trigger on
4027      // hover-less devices, and require :focus-visible (keyboard focus) for
4028      // the focus trigger — tap focus does not match :focus-visible.
4029      function deviceCanHover() {
4030        return !!(window.matchMedia && window.matchMedia('(hover: hover)').matches);
4031      }
4032      function isKeyboardFocus(el) {
4033        try { return !!(el && el.matches && el.matches(':focus-visible')); }
4034        catch (e) { return false; }
4035      }
4036      $triggers
4037        .off('.a11yTooltip')
4038        .on('mouseenter.a11yTooltip', function () {
4039          if (!deviceCanHover()) return;
4040          scheduleShow(this);
4041        })
4042        .on('focusin.a11yTooltip', function () {
4043          if (!isKeyboardFocus(this)) return;
4044          showTooltip(this);
4045        })
4046        .on('mouseleave.a11yTooltip focusout.a11yTooltip', function () {
4047          var $trigger = $(this);
4048          clearShowTimer($trigger);
4049          scheduleHide($trigger);
4050        });
4051
4052    }
4053
4054    function hideLiveAccessibleTooltips() {
4055      $(tooltipSelector).each(function () {
4056        var $trigger = $(this);
4057        clearHideTimer($trigger);
4058        clearShowTimer($trigger);
4059        if ($trigger.data('bs.tooltip')) {
4060          $trigger.tooltip('hide');
4061        }
4062      });
4063    }
4064
4065    function onAccessibleTooltipKeydown(e) {
4066      if (e.key === 'Escape' || e.keyCode === 27) {
4067        hideLiveAccessibleTooltips();
4068      }
4069    }
4070
4071    // Initialization runs repeatedly for MutationObserver batches. Keep one
4072    // document-level listener and query the live DOM on demand so removed
4073    // trigger collections are never retained by old closures.
4074    $(document)
4075      .off('keydown.a11yTooltip')
4076      .on('keydown.a11yTooltip', onAccessibleTooltipKeydown);
4077
4078    window.initAccessibleTooltips = initAccessibleTooltips;
4079    initAccessibleTooltips(tooltipSelector);
4080    if (window.MutationObserver) {
4081      new MutationObserver(function (mutations) {
4082        mutations.forEach(function (mutation) {
4083          if (mutation.type === 'attributes' && (
4084              mutation.attributeName === 'title' ||
4085              mutation.attributeName === 'data-original-title' ||
4086              mutation.attributeName === 'data-tooltip')) {
4087            if (mutation.target.matches && mutation.target.matches(tooltipSelector)) {
4088              initAccessibleTooltips(mutation.target);
4089            }
4090          }
4091          if (mutation.type === 'childList') {
4092            mutation.addedNodes.forEach(function (node) {
4093              if (!node || node.nodeType !== 1) return;
4094              if (node.matches && node.matches(tooltipSelector)) {
4095                initAccessibleTooltips(node);
4096              }
4097              if (node.querySelectorAll) {
4098                node.querySelectorAll(tooltipSelector).forEach(function (child) {
4099                  initAccessibleTooltips(child);
4100                });
4101              }
4102            });
4103            // Bootstrap appends the tooltip element to <body> separately from
4104            // its trigger. If a trigger is removed while its tooltip is open
4105            // (e.g. a step nav re-render), the tooltip element is left behind
4106            // and stays visible forever. Sweep any orphans whose
4107            // aria-describedby target no longer points at a live trigger.
4108            mutation.removedNodes.forEach(function (node) {
4109              if (!node || node.nodeType !== 1) return;
4110              cleanupOrphanedTooltipsFor(node);
4111              if (node.querySelectorAll) {
4112                node.querySelectorAll('[aria-describedby]').forEach(cleanupOrphanedTooltipsFor);
4113              }
4114            });
4115          }
4116        });
4117      }).observe(document.documentElement, {
4118        attributes: true,
4119        attributeFilter: ['title', 'data-original-title', 'data-tooltip'],
4120        childList: true,
4121        subtree: true
4122      });
4123    }
4124
4125    function cleanupOrphanedTooltipsFor(node) {
4126      var id = node.getAttribute && node.getAttribute('aria-describedby');
4127      if (!id) return;
4128      var tip = document.getElementById(id);
4129      if (!tip || !tip.classList || !tip.classList.contains('tooltip')) return;
4130      // Only remove if no live trigger still references this tip id.
4131      if (!document.querySelector('[aria-describedby="' + id + '"]')) {
4132        tip.parentNode && tip.parentNode.removeChild(tip);
4133      }
4134    }
4135
4136    // Keep the navbar hamburger's aria-expanded in sync with the Bootstrap 3
4137    // collapse state (SC 4.1.2). The toggle button points at the collapse
4138    // via data-target, so its state should track shown/hidden transitions.
4139    $('.navbar-collapse').on('show.bs.collapse hidden.bs.collapse', function (e) {
4140      var expanded = e.type === 'show';
4141      $('.navbar-toggle[data-target]').each(function () {
4142        var tgt = $(this).attr('data-target');
4143        if (tgt && $(e.target).is(tgt)) {
4144          $(this).attr('aria-expanded', expanded ? 'true' : 'false');
4145        }
4146      });
4147    });
4148    $(document).on('show.bs.collapse hidden.bs.collapse', '.collapse', function (e) {
4149      $('[data-toggle="collapse"][aria-controls="' + this.id + '"]').attr('aria-expanded', e.type === 'show' ? 'true' : 'false');
4150    });
4151  });
4152</script>
4152
4153
4154<script>
4155  // Carousel
4156  (function ($) {
4157    "use strict";
4158    var $container = $('.portfolio'),
4159      $items = $container.find('.portfolio-item'),
4160      portfolioLayout = 'fitRows';
4161
4162    if ($container.hasClass('portfolio-centered')) {
4163      portfolioLayout = 'masonry';
4164    }
4165
4166    $container.isotope({
4167      filter: '*',
4168      animationEngine: 'best-available',
4169      layoutMode: portfolioLayout,
4170      animationOptions: {
4171        duration: 750,
4172        easing: 'linear',
4173        queue: false
4174      },
4175      masonry: {
4176      }
4177    }, refreshWaypoints());
4178
4179    function refreshWaypoints() {
4180      setTimeout(function () {
4181      }, 1000);
4182    }
4183
4184    $('nav.portfolio-filter ul a').on('click', function () {
4185      var selector = $(this).attr('data-filter');
4186      $container.isotope({ filter: selector }, refreshWaypoints());
4187      $('nav.portfolio-filter ul a').removeClass('active');
4188      $(this).addClass('active');
4189      return false;
4190    });
4191
4192    function getColumnNumber() {
4193      var divWidth = $('#carousellist').width(),
4194        columnNumber = 1;
4195
4196      if (divWidth > 800) {
4197        columnNumber = 5;
4198      } else if (divWidth > 600) {
4199        columnNumber = 4;
4200      } else if (divWidth > 400) {
4201        columnNumber = 3;
4202      } else if (divWidth > 200) {
4203        columnNumber = 2;
4204      } else if (divWidth > 100) {
4205        columnNumber = 1;
4206      }
4207      return columnNumber;
4208    }
4209
4210    function setColumns() {
4211      var divWidth = $('#carousellist').width(),
4212        columnNumber = getColumnNumber(),
4213        itemWidth = Math.floor(divWidth / columnNumber);
4214
4215      $container.find('.portfolio-item').each(function () {
4216        $(this).css({
4217          width: itemWidth + 'px'
4218        });
4219      });
4220    }
4221
4222    function setPortfolio() {
4223      setColumns();
4224      $container.isotope('reLayout');
4225    }
4226
4227    $container.imagesLoaded(function () {
4228      setPortfolio();
4229    });
4230
4231    $('#carousellist').on('resize', function () {
4232      setPortfolio();
4233    });
4234  })(jQuery);
4235</script>
vendor: 1 bytes, line 4235
4235
4236<script>
4237  jQuery(document).ready(function ($) {
4238    var slider = $('.my-slider').unslider({
4239      animation: 'fade', autoplay: true, arrows: false
4240    });
4241
4242    $('.my-slider').height('initial');
4243
4244    data = slider.data('unslider');
4245
4246    $(".portfolio-item").on({
4247      mouseenter: function () {
4248        data.stop();
4249      },
4250      mouseleave: function () {
4251        data.start();
4252      }
4253    });
4254  });
4255</script>
4255
4256
4257<script>
4258
4259  jQuery.fn.selectInner = function () {
4260    var doc = document;
4261    var element = this[0];
4262
4263    if (doc.body.createTextRange) {
4264      var range = document.body.createTextRange();
4265      range.moveToElementText(element);
4266      range.select();
4267    }
4268    else if (window.getSelection) {
4269      var selection = window.getSelection();
4270      selection.removeAllRanges();
4271
4272      var range = document.createRange();
4273      range.selectNodeContents(element);
4274
4275      selection.addRange(range);
4276    }
4277  };
4278
4279  // since there is currently no way to use custom plugins on gh-pages
4280  // flickr integration is done on demand via javascript
4281
4282  var flickr_api = "https://api.flickr.com/services/rest/";
4283  var flickr_api_key = "";
4284
4285  function flickr_photo_url(photo) {
4286    return "https://farm" + photo.farm
4287      + ".staticflickr.com/" + photo.server + "/"
4288      + photo.id + "_" + photo.secret + "_b.jpg";
4289  }
4290
4291  var blueimp_gallery_cache = [];
4292
4293  function blueimp_gallery(photoset_id) {
4294    blueimp.Gallery(blueimp_gallery_cache[photoset_id]
4295      , { useBootstrapModal: false, event: event, container: '#blueimp-gallery' });
4296  }
4297
4298  function blueimp_video(photoset_id) {
4299    blueimp.Gallery(blueimp_gallery_cache[photoset_id]
4300      , { useBootstrapModal: false, event: event, container: '#blueimp-gallery' });
4301  }
4302
4303  function flickr_photosets(photoset_id) {
4304    if (photoset_id in blueimp_gallery_cache) {
4305      blueimp_gallery(photoset_id);
4306      return;
4307    }
4308
4309    var spin_attributes = {
4310      lines: 12,
4311      length: 12,
4312      width: 4,
4313      radius: 16,
4314      corners: 1,
4315      zIndex: 1,
4316    };
4317
4318    $('#' + photoset_id).spin(spin_attributes);
4319
4320    $.getJSON(flickr_api,
4321      {
4322        method: "flickr.photosets.getPhotos",
4323        api_key: flickr_api_key,
4324        photoset_id: photoset_id,
4325        format: "json",
4326        nojsoncallback: 1
4327      })
4328
4329      .done(function (data) {
4330        var blueimpl_gallery = [];
4331
4332        $.each(data.photoset.photo, function (i, photo) {
4333          blueimpl_gallery.push({ href: flickr_photo_url(photo), title: photo.title })
4334        });
4335
4336        blueimp_gallery_cache[photoset_id] = blueimpl_gallery;
4337        blueimp_gallery(photoset_id);
4338      })
4339      .fail(function (data, textStatus, error) {
4340        var $target = $('#' + photoset_id);
4341        $target.attr({ role: 'alert', 'aria-live': 'assertive' });
4342        $target.text('Photos could not load right now. Check your connection and try again later.');
4343        if (window.console && console.warn) console.warn('Flickr photoset load failed:', textStatus, error);
4344      })
4345      .always(function () {
4346        var spinner = $('#' + photoset_id).data().spinner;
4347        if (spinner)
4348          spinner.stop();
4349      });
4350  }
4351
4352  $(document).ready(function () {
4353    // assign flickr photosets to thumbnails
4354    $('.flickr').on('click', function (event) {
4355      event.preventDefault();
4356      flickr_photosets($(this).attr("id"));
4357    });
4358
4359    // assign bibtex select scripts
4360    
4361  });
4362
4363  // contact form validation
4364  $("#contact-form").validate(
4365    {
4366      rules:
4367      {
4368        name: { required: true },
4369        _replyto: { required: true, email: true },
4370        message: { required: true, maxlength: 1024 }
4371      },
4372
4373      errorClass: 'error form-control-static text-danger',
4374      errorElement: 'div',
4375
4376      // Ensure every error message has a stable id, is linked to its input
4377      // via aria-describedby, is wrapped in a polite live region, and that
4378      // the input is flagged aria-invalid="true" (SC 3.3.1, 4.1.3).
4379      errorPlacement: function (error, element) {
4380        var inputId = element.attr('id') || element.attr('name');
4381        var errId = 'err-' + inputId;
4382        error.attr('id', errId);
4383        error.attr('role', 'alert');
4384        error.attr('aria-live', 'polite');
4385        element.attr('aria-describedby', errId);
4386        element.attr('aria-invalid', 'true');
4387        error.insertAfter(element);
4388      },
4389
4390      highlight: function (label) {
4391        $(label).closest('.form-group').addClass('has-error');
4392        $(label).attr('aria-invalid', 'true');
4393      },
4394
4395      unhighlight: function (label) {
4396        $(label).removeAttr('aria-invalid');
4397      },
4398
4399      success: function (label, element) {
4400        $(label).closest('.form-group').removeClass('has-error');
4401        $(element).removeAttr('aria-describedby');
4402        $(element).removeAttr('aria-invalid');
4403        $(label).remove();
4404      },
4405
4406      submitHandler: function (form) {
4407        $.ajax(
4408          {
4409            url: form.action,
4410            type: form.method,
4411            data: $(form).serializeJSON()
4412          });
4413      }
4414    });
4415
4416</script>
vendor: 1 bytes, line 4416
4416
4417<script src="/js/audio-player.js"></script>
vendor: 1 bytes, line 4417
4417
4418<script src="/js/se-gym.js"></script>
vendor: 1 bytes, line 4418
4418
4419<script src="/js/study-schedule.js"></script>
4419
4420
4421  
4421<script src="/js/se-gym-hero-avatar.js?v=20260927-sebook-landing-hero" defer></script>
4421
4422
4423</body>
4424
4425</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.