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'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 35L</a>, 362 <a href="/SEBook/CS130_bookmarks.html">CS 130</a>, and 363 <a href="/SEBook/CS131_bookmarks.html">CS 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 & 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 & 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 & debugger"> 2836 <a href="/SEBook/tools/regex-simulator.html" class="sebook-search-result-link"> 2837 <span class="sebook-search-result-title">Python RegEx Simulator & 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 · 3496 <a href="/shortcuts/">Keyboard shortcuts</a> 3497 · 3498 <a href="/settings/">My Settings</a> 3499 · 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 & 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 →</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 − 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.