-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlogDesign.html
More file actions
591 lines (581 loc) · 34.6 KB
/
BlogDesign.html
File metadata and controls
591 lines (581 loc) · 34.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
<!DOCTYPE html>
<html>
<!--
Blog.html
Blog introduction
-->
<head>
<title>Blog design</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- <link rel="icon" type="image/x-icon" href="./images/favicon.ico" /> -->
<link rel="stylesheet" href="css/StylesPhoto.css" />
<link rel="stylesheet" href="css/StylesSizerComp.css" />
<!-- PageFrame infrastructure -->
<link rel="stylesheet" href="css/StylesPageFrameDefaults.css" />
<link rel="stylesheet" href="css/StylesPageFrameStructure.css" />
<link rel="stylesheet" href="css/StylesPageFrameMenus.css" />
<link rel="stylesheet" href="css/StylesPageFrameThemePython.css" />
<link rel="stylesheet" href="css/StylesWebComponents.css" />
<script src="js/ScriptsWebComponents.js"></script>
<!--<script src="js/ScriptsPageFrameDefaults.js"></script>-->
<script src="js/ScriptsPageFramePosts.js"></script>
<script src="js/ScriptsPageFramePagesPosts.js"></script>
<script src="js/ScriptsPageFrameKeyboard.js"></script>
<!-- No need for Pages script for pages with no next or prev pages -->
<!--<script src="js/ScriptsPageFramePages.js"></script>-->
<!-- <script src="js/ScriptsTemplate.js"></script>
<link rel="stylesheet" href="css/StylesTemplate.css" /> -->
<style>
h3 {
margin-top: 1.5em;
}
#subtitle {
margin-top: 0.4em;
margin-bottom: 0.3em;
}
#github header summary {
border: 1px solid var(--light);
}
#github summary {
padding-right: 2em;
}
/* #github .menuHead {
margin:0em -0.25em 0.0em -0.25em;
padding:0.25em 0.5em;
} */
</style>
<script>
function load() {
initialize();
//loadif();
}
</script>
<style>
#github note {
display: block;
width:max-content;
border:1px solid red;
padding:0.5em 1.0em;
margin:0.5em 0em;
}
#github .bargraph {
border: 1px solid var(--dark);
/* background-color: #bbb; */
padding: 0.1em 0.5em;
font-size:0.9em;
}
#github table {
border:2px solid var(--dark);
}
#github table td {
padding:0.25em 1.0em;
border:none;
}
body {
user-select:none;
}
</style>
<script>
function clickstat() {
// prevent parent click event handling
event.stopImmediatePropagation();
}
</script>
</head>
<body id="github" onload="load()" style="position:relative;">
<a id="Next" href="BlogPrinciples.html">Next</a>
<a id="Prev" href="Blog.html">Prev</a>
<page-frame>
<frame-header>
<nav id="navbar"></nav>
</frame-header>
<main id="main">
<div id="about" onclick="this.style.display = 'none'">about</div>
<div id="page">Blog: SW Design</div>
<div id="modified">11/23/2024</div>
<div id="hlp"></div>
<a id="top"></a>
<content style="height:100vh; position:relative;">
<header onclick="loadif()" style="cursor:pointer;">
<!-- <a target="_blank" class="repoLink" href="https://github.com/JimFawcett">github Repositories</a> -->
<hgroup id="pagetitle" style="border: 2px solid var(--dark);">
<h1 id="title">Blog: SW Design</h1>
<h3 class="indent" id="subtitle">
concept, structure, flow of execution
</h3>
</hgroup>
<!-- <img style="width:100%; margin:-0.1em 0em; border:2px solid var(--dark); padding:0.5em; background-color:var(--light);" src="Pictures/officestrip3a.svg" /> -->
<div class="darkItem" onclick="loadif()" style="cursor:pointer; position:relative; padding:0.0em 0em 0.25em 0em; margin-top:-0.50em; border:2px solid var(--dark);">
<a class="repoLinks" target="_blank" href="https://github.com/JimFawcett" style="color:var(--atten); margin-left:1.5em;">About</a>
<div style="font-size:0.9em; position:absolute; top:0.1em; right:1.5em;">click to toggle Site Explorer</div>
<div style="height:0.5em;"></div>
</div>
</header>
<h3>Initial Thoughts:</h3>
Design of software encompasses many things:
<ol>
<li id="concept">
<strong>Concept:</strong><br />
Ideas about the project's functionality, who the users are, what they need, and any critical issues about how those
needs will be served, e.g., usability, complexity, safety, security, and robustness.
<div style="height:0.0em;"></div>
<details>
<summary>More</summary>
<hr />
<topic-block class="tight">
<div style="height:0.75em;"></div>
Let's explore a project concept by looking at the projects for <a href="https://ecs.syr.edu/faculty/fawcett/handouts/webpages/CSE687.htm">CSE687 - Object Oriented Design</a>,
Fall 2018.
<div style="height:0.75em;"></div>
<ul class="tights" style="list-style-type: disc;">
<li>
In <strong>Project #1</strong> we built a <a href="ProjStmts-687/Project1-F2018.htm">single-user test harness</a>
that executes a sequence of tests, each of which implements an ITest interface,
in the context of a try-catch block and reports results, using an
executor class, so that we don't need to write multiple try-catch blocks and don't need to write multiple
IO statements. You will find a diagram in the Project #1 statement, linked above, that shows how all the projects
will fit together to result in a useful testing facility for a professional project.
</li>
<li>
<strong>Project #2</strong> packages the single-user test harness into a stand-alone executable that will
become part of a <a href="ProjStmts-687/Project2-F2018.htm">multi-user test harness</a>.
</li>
<li>
<strong>Project #3</strong> builds a <a href="ProjStmts-687/Project3-F2018.htm">process pool</a> that uses asynchronous
message-passing communication to support control and message passing between a test harness and it's child
tester processes, so that tests can run concurrently without danger of rouge test code taking down the whole test harness.
</li>
<li>
Finally, <strong>Project #4</strong> adds a Graphical User Interface, based on C# Windows Presentation Foundation (WPF)
that builds a <a href="ProjStmts-687/Project4-F2018.htm">Remote Test Harness</a>, by interoperating with our C++ communication channel through a C++\CLI translater, that converts messages and calls
from managed C# to native C++ and back.
</li>
</ul>
<div style="height:0.75em;"></div>
The concept for this sequence is nicely illustrated by the diagrams, presented in each of the project statements, linked above.
Each project progressively adds functionality to the results of previous projects, much like agile "sprints".
<div style="height:0.75em;"></div>
Users for each project, except the last, are other software components. Developers and Quality Assurance Engineers are
the users of the final project.
<div style="height:0.75em;"></div>
The project structure is shown clearly by the diagrams presented in statements for Projects
<a href="ProjStmts-687/Project1-F2018.htm">#1</a>,
<a href="ProjStmts-687/Project2-F2018.htm">#2</a>,
<a href="ProjStmts-687/Project3-F2018.htm">#3</a>,
<a href="ProjStmts-687/Project4-F2018.htm">#4</a>.
<div style="height:0.75em;"></div>
Critical issues are concerned mostly with usability of the multi-user test harness. If it isn't easy to use
developers and quality assurance will find other ways to do their testing, and this development will be wasted effort.
<div style="height:0.75em;"></div>
</topic-block>
<hr />
<div style="height:0.75em;"></div>
</details>
<div style="height:0.0em;"></div>
Design usually begins with <a target="_blank" href="BlogOCD.html">concept development</a> - establishing user needs, critical issues, and
top level package structure. Making a list of Tasks the software must complete to satisfy
user needs is often a good way to start. Each task is a candidate to become a top-level package.
We want our packages to be focused on a single activity so they are cohesive. We want them to be
independently testable and composable with top-level packages for the other tasks.
<div style="height:0.75em;"></div>
The project concept is its most abstract description and should be invariant over the lifetime
of the development. Specifications may change because neither customers nor developers have
perfect foresight. But they both need an invariant top-level view of the project even though many concrete details
may be changing; the concept document plays this role.
</li>
<li id="abstractions">
<strong>Abstractions:</strong><br />
Abstractions are conceptual models for the entities that are part of a software design.
Entities are concrete things from the problem domain like products and orders, customers, employees,
and also for the solution domain, like Parsers, Tasks, ThreadPools, etc., where we may need to build complex
data structures that define and manage program state.
<div style="height:0.0em;"></div>
<details>
<summary>more</summary>
<hr />
<div style="margin:0.75em;">
Developing problem domain abstractions usually comes early in the design process, and that development may be obvious for domain experts.
Having a set of abstractions helps us define
the parts that make up a system and the actions the parts take during the system's lifetime.
<div style="height:0.75em;"></div>
Frequently abstractions turn into classes of the same name. We use the class relationships: inheritance,
composition, aggregation, and using to model behaviors of the problem domain entities and actors.
These are captured with the Universal Modeling Language (UML) - class, activity, and sequence diagrams.
<div style="height:0.75em;"></div>
The process of defining abstractions and building their concrete representations continues in the
solution domain. For the solution parts aliases can be a useful tool for thinking about and building
that part's abstraction.
<topic-block class="tight">
<div style="height:0.75em;"></div>
The C++11 using construct represents an alias for some type. Here's an example declaring a symbol table abstraction
with aliases:
<div>
<pre style="font-family:Consolas,monospace; font-weight:bold;">
<c-s>
template<typename typeinfo>
class SymbolTable
{
public:
using Type = std::string;
using Name = std::string;
using Record = std::tuple<type, name, typeinfo>
using Records = std::vector<record>
void add(const Record& record) { _records.push_back(record); }
Record& operator[](size_t i);
Record operator[](size_t i) const;
Records FindName(const Name& name);
Records FindType(const Type& type);
Records GetRecords() { return _records; }
private:
Records _records;
};
</c-s> </pre>
<div class="indent">
We want to build the symbol table to record results of a type analysis, as outlined in the next paragraph. A record in the symbol table
will hold information about a declaration, e.g., its type, name of the instance, and additional information like file name and line numbers.
<div style="height:0.75em;"></div>
We're not sure yet about all the details, so we represent that by a template parameter and bind it all together into a symbol table
record using a tuple.
</div>
</div>
<div style="height:0.75em;"></div>
</topic-block>
</div>
<hr />
<div style="height:0.75em;"></div>
</details>
</li>
<li id="flowexec">
<strong>Flow of Execution:</strong><br />
What computational activites are needed and how will they be ordered?
<div style="height:0.0em;"></div>
<details>
<summary>more</summary>
<hr />
<div style="margin:0.75em 0em">
Building a task list also helps us decide on an execution model. How must the tasks be ordered?
Are there opportunities for parallel execution? Should computation be configured into two or more
phases each of which makes some specific transformations on the project's working state?
<div style="height:0.75em;"></div>
<div class="indent">
For example, suppose that we want to analyze dependency between files based on use of types,
global functions, and global data. If File A uses a type or global function or data defined
in File B then A depends on B.
<div style="height:0.75em;"></div>
So, in Pass #1, we will <a href="blogParser.html">parse</a> each
file in our working set to discover the types, global functions, and global data it defines,
and store that in a symbol table along with the file name.
<div style="height:0.75em;"></div>
In Pass #2, we simply tokenize
each file and check to see if each token is a key in the symbol table. If so, this file depends
on the file stored in the symbol table for that key.
</div>
<div style="height:0.75em;"></div>
Building a data flow model may also be a good way to start thinking about execution. We need to ask what
input data state is required for a task to carry out its assignment. How does that task need to restructure
its input and what new data must it generate for the next task to consume?
<div style="height:0.75em;"></div>
<div class="indent">
For file dependency analysis the input working set consists of the file set. The output of Pass #1
consists of a symbol table holding names of all the types, global functions, and global data along with
the name of the file where defined.
<div style="height:0.75em;"></div>
Pass #2 uses the file set and symbol table to generate a set of dependency relationships between
files. We might represent that with XML or Json or links in a database table.
</div>
</div>
<hr />
<div style="height:0.75em;"></div>
</details>
</li>
<li id="structure">
<strong>Structure:</strong><br />
Structure is some arrangement of parts. For software development the parts are:
<ul class="tights" style="list-style-type: disc;">
<li>
Functions and classes - the fundamental units of design.
</li>
<li>
Packages - collections of functions and classes in one or two source code files focused on a single activity. For C and C++ a package has two
files, a header file with declarations and inline definitions, and an implementation
file containing the non-inline functions and a main function where execution may begin<sup>1</sup>.
A package in Java or C# is a single file containing these same parts.
</li>
<li>
Modules - collections of packages that combine to deliver some major functionality.
</li>
<li>
Programs - combinations of modules that provide everything required to build an executable.
</li>
<li>
Systems - combinations of programs that offer a complete working product.
</li>
</ul>
<details>
<summary>more</summary>
<hr />
<div style="margin:0.75em 0em">
Design decides the names and functionalities of the principle parts and how they interact. What dependencies are needed
between the parts?
What information has to be generated and made accessible by the parts?
Here are several views of software structure:
<ul class="tights" style="list-style-type: disc;">
<li>
Logical models using classes and class relationships
</li>
<li>
Allocation of classes to packages and package dependencies
</li>
<li>
Establishing module boundaries with interfaces and object factories
</li>
<li>
Forking execution into threads and processes
</li>
<li>
Packaging of execution in binary files - executables and loadable modules
</li>
<li>
Distribution of execution across processes, machines, and networks
</li>
</ul>
<div style="height:0.75em;"></div>
Each task identified during concept development is a candidate for the
operation of a package. By this time we have a good idea of what that task needs to accomplish and
what input state it needs to begin processing. The data flow model tells us how we need to order and couple the packages
into modules and programs.
<div style="height:0.75em;"></div>
<topic-block class="tight">
<div style="height:0.75em;"></div>
Several of the structure views cited above are illustrated by a prototype I developed for a
<a href="BlogMessagePassingComm.html">Message-passing Communication System</a>. Message-passing is defined, here,
with a class hierarchy of communicators, each of which has a blocking message queue and a child thread
that processes received messages. Find more details in <a href="BlogActiveObjects.html">Blog on Active Objects</a>.
<div class="right clear" style="margin: 10px; padding: 10px;">
<img name="CommObjs" width="620" onmouseover="CommObjs.width='620'" onmouseout="CommObjs.width='620'" src="Pictures/CommObjs.png" />
<div class="center">Figure 2 - Document Vault Demo using Message Dispatching in the Server</div>
</div>
<div style="height:0.75em;"></div>
These classes are allocated to packages for sending, receiving, and dispatching messages. Additional
communicator classes are used to define the behavior of clients and servers.
<div style="height:0.75em;"></div>
Communication activities are illustrated with an Activity Diagram which is a view of program tasks at
a slightly lower level of detail.
<div style="height:0.75em;"></div>
Send and Receive communicators and their task-based communicator colleagues
pass messages between machines in a network or across the internet. This allows us to conveniently
distribute processing across client and server machines. The server is the center for sharing
resources between each of the clients which provide human access to the system.
<div style="height:0.75em;"></div>
Receive communicators contain a dispatcher that routes messages to named task-based communcators.
The dispatcher serves as a mediator handling all message traffic into and out of the local process or machine.
<div style="height:0.75em;"></div>
Using a mediator makes adding new functionality very simple. We derive a communicator from the AbstractCommunicator,
register it with the dispatcher, and clients can immediately begin using the new functionality. No other changes
are needed.
<div style="height:0.75em;"></div>
</topic-block>
<div style="height:0.75em;"></div>
Tasks are a nice way of partitioning design and implementation effort.
We can start building some of the task-based packages while we are still thinking about how to
design and implement others. This allows us to build incrementally and share development across
multiple teams.
<div style="height:0.75em;"></div>
For each package we may carry out the same process on a smaller scale to determine
lower level package structure and operations. Using these design views - Tasks, activities, classes, packages, and modules
allows us to think critically about our project before we become emeshed in its implementation
details.
</div>
<hr />
<div style="height:0.75em;"></div>
</details>
</li>
<li id="communication">
<strong>Communication and Accessibility:</strong><br />
How does information flow between the various parts and how are event notifications routed
to parts with need to know? Is information pushed by the creators or pulled by the
consumers?
<details>
<summary>more</summary>
<hr style="margin:0.75em 0em;" />
<div>
Communication is concerned with routing commands and event notifications as well as making
data generated in one part of the code accessible to any other parts that need to use it.
for example, an executive package communicates with each of its child packages, e.g., the packages that are responsible
for each task of the program, to activate them at the appropriate phase of computation and may receive
notifications of errors the child encountered.
<div style="height:0.75em;"></div>
Often
data flows between class instances in each top level package through method calls and may evolve
in simple and intuitive ways. However, as systems get larger data access may become considerably more
complicated.
<div style="height:0.75em;"></div>
Careful design of class ownership is the key to effective communication: a class has
access to the public interface of its parts - composed and aggregated instances of other classes - and can directly send and receive data
as well as issue commands to them and receive notifications from them.
<div style="height:0.75em;"></div>
<div class="indent">
The <a href="blogParser.html">parser</a> is an interesting example of the use of ownership.
Its object factory, configureParser, owns all the Rules and Actions that determine how parsing
is executed. When configureParser creates each action it passes a reference to a data Repository to them.
Actions can store data and use data that other actions have added. Thus an action
can use the results of other actions that it otherwise has no access to.
</div>
<div style="height:0.75em;"></div>
We can, of course, openly share data in ways that make it accessible throughout an entire process or
even for any process running in the same machine.
<ul class="tights" style="list-style-type: disc;">
<li>
We can declare a static member of some class and make it accessible through the class's public interface;
then any other code running in the same process that declares an instance of the wrapper class has access to the static instance.
</li>
<li>
Global data in C and C++ programs also provides process wide sharing, but in a much less
controllable way and is usually avoided.
</li>
<li>
We can also share through machine wide resources like files and shared memory.
</li>
</ul>
<div style="height:0.75em;"></div>
We occasionally resort to open sharing using one of these techniques but need to recognize
that open sharing comes with costs: need to ensure thread-safe access in a concurrent environment,
and problems with conflicts in use, e.g., two methods using the shared datum in conflicting ways.
<div style="height:0.75em;"></div>
Open sharing makes it considerably more difficult to think critically about operations of the
code and to ensure they are correct.
</div>
<hr style="margin:0.75em 0em;" />
</details>
</li>
<li id="errorhandling">
<strong>Error Handling:</strong><br />
How are errors handled by the design? Is each part responsible for it's own error handling
or is there some central logging and reaction needed? Errors often affect the system state.
How is that state recovered or reinitialized?
<details>
<summary>more</summary>
<hr style="margin:0.75em 0em" />
<div class="hider">
Error handling comes in two parts - detection and recovery. How we handle these is very much a
function of the context in which the program operates. If the program is a demonstration or prototype
we may be fairly casual about managing errors. If processing may affect usability, wealth, security, or safety,
error handling becomes an essential ingredient in system design.
<div style="height:0.75em;"></div>
You have these choices when faced with errors:
<ul style="list-style-type: disc;">
<li>
Assert that some condition is true. That is an easy way to detect some forms of errors, but
is useless for recovery since Asserts default to program termination.
</li>
<li>
Provide and use error codes as return values of functions. That has been widely used. It may
be effective in some specific situations - did my socket connect to its endpoint? In general, though,
we make frequent checks for rare events. That doesn't seem like a good use of CPU cycles. As well,
it's difficult to ensure that every place an error code is returned is checked. Also, checking error codes results
in error handling code distributed to every place an error code is visible.
</li>
<li>
Use Exceptions. When an error is detected we create and throw an exception. That causes, in C++,
the destruction of every successfully constructed object in the enclosing try block. Each try block has
a chain of catch clauses. If one of them matches the type of the exception instance its code is executed
to start the recovery process.
<div style="height:0.75em;"></div>
Note that a thrown exception interupts the expected execution flow and destroys possibly all the
important state computed in the try scope up to the point where the exception occurred. That means
that recovery has to reinitialize the destroyed objects and somehow recover their state.
</li>
</ul>
Error handling usually entails using error codes in the few places where processing can't proceed in the
presence of errors - we can't open a file or connect to an endpoint. Otherwise we design the placement
of try blocks and think carefully about their catch clauses and how we can use them to recover.
This is a fundamental part of program design and is harder to retrofit after an implementation is nearly complete than
to make error handling a part of the early design process.
<div style="height:0.75em;"></div>
To design error handling we start by making a catalog of all the errors that could happen:
<ul class="tight">
<li>
User inputs: command line arguments, entries in web pages or application interfaces.
</li>
<li>
File and directory handling: do they exist, are they locked by another program, are our
security credentials insufficient for access.
</li>
<li>
Connecting to remote endpoints: are they not currently available, do we have incorrect urls?
</li>
<li>
Devices and services we use may have errors or are not currently available.
</li>
</ul>
<div style="height:0.75em;"></div>
We then think about the actions the program needs to take, for each error, to recover. We also plan
notifications to the users so they understand what is happening to the computation.
<div style="height:0.75em;"></div>
Whenever possible we attempt to continue processing in the presence of errors. For example,
if we are processing a number of files an error accessing one of them should not stop us
from processing the rest.
<div style="height:0.75em;"></div>
The best error handling is to avoid errors by design. For example, we should never use absolute paths
in our code. Usually we will specify paths relative to the current directory. That way our program
can be successfully moved, along with its reference directories, to another machine that has a different directory structure than our
development environment. When that isn't possible we can use configuration files that our code reads
on startup to establish key paths and files. When we port the application to a different machine we
simply edit the configuration to match its new environment.
</div>
<hr style="margin:0.75em 0em" />
<div style="height:0.25em;"></div>
</details>
</li>
</ol>
<p />
<hr />
<ol>
<li>
Each package contains a test stub main function for construction testing. That is surrounded by
compiler declarations #ifdef TEST_PACKAGE and #endif. If we define for compilation the TEST_PACKAGE
string, where PACKAGE is the name of the package, then the compiler will include the main and we can
run the package in stand-alone mode. If the string is not defined then the compiler's preprocessor
does not include this code so we can combine the package with others to make a program.
</li>
</ol>
<div style="height:0.75em;"></div>
<img class="photo" src="Pictures/campusStrip.jpg" alt="Newhouse" style="width:100%;" />
<div style="height:0.75em;"></div>
</content>
<a id="bottom"></a>
<page-TOC id="pages" style="display:none;">
</page-TOC>
<page-sections id="sections" style="display:none;">
<menu-elem style="width:0.0em"> </menu-elem>
<menu-elem class="secElem"><a href="#bottom">bottom</a></menu-elem>
<menu-elem class="secElem"><a href="#errorhandling">errorhandling</a></menu-elem>
<menu-elem class="secElem"><a href="#communication">communication</a></menu-elem>
<menu-elem class="secElem"><a href="#structure">structure</a></menu-elem>
<menu-elem class="secElem"><a href="#flowexec">flowexec</a></menu-elem>
<menu-elem class="secElem"><a href="#abstractions">abstractions</a></menu-elem>
<menu-elem class="secElem"><a href="#concept">concept</a></menu-elem>
<menu-elem class="secElem"><a href="#top">top</a></menu-elem>
<div class='darkItem popupHeader' style="padding:0.25em 2.0em;" onclick="this.parentElement.style.display='none'">Sections</div>
</page-sections>
</main>
<frame-footer>
<menu-item style="width:2.0em;"> </menu-item>
<menu-elem id="nextLink2" onclick="bottomMenu.next()">Next</menu-elem>
<menu-elem id="prevLink2" onclick="bottomMenu.prev()">Prev</menu-elem>
<menu-elem id="pgbtn" onclick="bottomMenu.pages()">Pages</menu-elem>
<menu-elem onclick="bottomMenu.sections()">Sections</menu-elem>
<menu-elem onclick="bottomMenu.about()">About</menu-elem>
<menu-elem id="kysbtn" onclick="storyHlpMenu.keys()">Keys</menu-elem>
<menu-elem style="margin-right:1em">
<span id="loc" style="display:inline-block; font-weight:normal"></span>
</menu-elem>
</frame-footer>
</page-frame>
<script>
let loc = document.getElementById("loc");
let fn = window.location.href.split(/\/|\\/).pop();
loc.innerHTML = fn + ":";
</script>
</body>
</html>