-
Notifications
You must be signed in to change notification settings - Fork 16
/
DemoScript.txt
215 lines (156 loc) · 7.12 KB
/
DemoScript.txt
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
Module 1:
===========================================================
This module shows some of the new features. I picked these
features first because they are easy to explain for
simple use cases, and they should be good 'hooks' for the
audience.
Step one: Create the project, add an EvilGenius Class.
The first version of the EvilGenius class just has the
three properties.
2: Let's add an override of ToString() so the Evil
Genius can announce himself to the world. Do this using
the classic syntax. Include creating an EvilGenius in
Main() and writing a console message.
3. Translate ToString() to an expression bodied member.
Discuss benefits.
4. In Main, replace Console.WriteLine with WriteLine
and a static using. Point out that you don't get a
codefix for a static using. (Is that coming? Community
contribution?) Add the static using statement. Point
out that intellisense knows to filter namespaces vs.
classes depending on the presence of the 'static' keyword
in the using statement.
Let's take a few moments to talk about both of these features.
Expression Bodied Members:
. Must be single expressions (not multi-line anonymous functions)
. Could be LINQ queries, which might be complex
. great for read only properties (which we will cover later.)
Static Usings:
. De clutter source. (We know WriteLine is likely in theConsole
class)
. Consider Math class, even System.String.
. Later, we'll discuss how static usings work with Extension
methods.
Now, let's move on to the null coalescing operator
5. Change the henchman to a class (we will add more properties
and features later.)
6. Change ToString so that it also prints out the name of the
henchman, if present. I really don't want to do all that
typing to make it a classic style method, add if statements
and else clauses, depending on the presence of the henchman.
After this change, let's finish by showing how you can handle
ownership issues where an element may or may not implement
IDisposable.
7,8. In module 1, let's make it a very simple method added to
EvilGenius to 'replace' a henchman. Add the public RetireHenchman
method. Discuss alternatives, and show how the null coalescing
operator makes it easy to do the right thing, and safely
handle possible disposable henchman.
===========================================================
Module 2: Read Only Properties and Dictionary Initializers
Now, we make a couple changes to the EvilGenius class to
make use of Read Only Property enhancement.
M2.1: Change Minion to a readonly only property with a
backing field. Rename RetireMinion as ReplaceMinion, and
have it take a new minion. This means we can use
Interlocked.Exchange to be completely thread safe when
the minion is replaced.
. Talk about these changes for a bit.
M2.2: Evil Geniuses never change their name. Make that
a readonly property that is set during construction. Use
old syntax first.
M2.3 Go to the new syntax. Point out that the compiler
enforces correct behavior. With the new syntax, the Name
cannot be set in any method *except* the constructor.
Under the old method, well, you can put things anywhere.
Now, let's serialize a bunch of evil.
M2.4 Let's serialize Evil to and from JSON. Start with a
ToJSON method. The old way is just nasty, so let's not
even write that one. Just write the new one. Point out
that we've been able to use this kind of syntax with
lists and other ordered collections, but not with
associative containers.
.. Talk about the new NuGet interface.
M2.5: CHange how the minion is created. Point out that
no features are gone in the language. We can freely mix
the new dictionary initializers with the old syntx.
This new version matches our business rules a little
better. Not every evil genius has a minion.
M2.6 Time to Create FromJson.
This is a good time to use GitHub to grab this version.
Less C# 6, just code.
Key messages on this section: These features make it
easier to create types that are immutable, or types
that will be sent along the wire between different
machines.
===========================================================
On to Module 3:
Let's start with nameof. There are a number of places
where we can make our library better by using nameof.
Why: nameof uses the symbol name, so refactoring tools
make this work better.
M3.1: put nameof on the JSON keys. (not labelled on the
commit message. )
M3.2: Use an F2 refactoring to change the name of
the minion. Note that if fixes all the JSON areas.
M3.3: Add a constructor check on the evil genius.
Make sure the evil genius has a name. Use nameof
M3.4 Create an Evil Plan view model. INotifyPRopertyChanged
isn't being raised yet.
M3.5 Raise in the simplest classic way
M3.6: Naive implementation that doesn't check if a
handler is connected.
M3.7: classic thread safe handler.
M3.8: Elvis. Make sure to point out that it is
threadsafe.
M 3.9: use nameof
M 3.10: Re-implement the ToString() method using
string interpolation.
M 3.11: EvilHistory, part 1. Doesn't handle empty sequences.
M 3.12: Fix EvilHistory to work when there are no previous
elements
===========================================================
Module 4: Exception Filters and await in finally
Intro: In the last module, we added a check for null in the
EvilGenius constructor. As our evil empire grows, we're
going to run into production style problems: we'll encounter
problems we haven't seen in the lab.
We want to treat every problem we observe in the field as
an opportunity to improve the codebase. When errors occur,
add code that helps us debug. Add that code in a way that
we can leave it for the next developer, without impacting
regular performance.
So, let's look at what might happen.
M4.1: Try to create a nameless evil genius. Program crashes.
M4.2: (Note that it wasn't labeled in the commit message)
Catch the ArgumentNullException.
M4.3: comment out and show the errors.
M4.4: show a simple example that catches when the Param
name is 'name'. Discuss as an example. Better real world
examples would be HttpException.GetHttpCode().
M4.5: Log exception.
M4.6: Show how to break only when the debugger is
present. Point out that this is not a good case for
static using: when (IsAttached) isn't very meaningful.
M4.7: Add an async log errors method. Put it in the catch
clauses, and let that be the work getting done now.
==========================================================
Module 6:
The demo script has two main sections:
1. Let's review the EvilUtilities library and discuss the
coding practices. Let's look at the features and discuss
uses with possible plans for developers:
a. Should I replace old habits for an entire file on
every checkin?
b. Should I replace old habits for any code I'm actively
modifying?
c. Should I adopt the new habits, but leave old code
untouched?
d. Is this an example where I bent the new feature to a point
where the old version is likely more readable?
This is also a great time to answer any live questions that we
haven't addressed yet.
The second section will load Dustin's CSharpEssentials project
(https://github.com/DustinCampbell/CSharpEssentials) and
show how the Roslyn APIs can make it easier to automate the process
of adopting new practices.