The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

434457 (10) [Avatar] Offline
#1
Hi Jon,

I thought that instead of spamming the list with all my comments/opinions, I'd just put each chapter review into a separate post.
Below are my thoughts on Ch 6 - right or wrong. Please take it as constructive criticism and not as an affront - just what I was thinking as I was reading through.

Cheers,
Willem van Ketwich


Chapter 6


p1.

other features contribut to


should be contribute

p1.

this sentence could be re-worded - I didn’t understand it on first read:

Properties allow us to differentiate between the API a type exposes to allow users to access and manipulate its state, and the implementation detail around how that state is maintained.


e.g.

Properties have the advantage over non-properties (such as fields, methods, etc.) of specifying the interface that a type (class/struct, etc.) exposes to allow users to access and manipulate its state, over merely specifying the implementation detail around how that state in the type in maintained.


p2/3:

but it turns out we’re not very good at predicting which properties might need extra code later on


is there any evidence for this or is it just an opinion? a reference maybe?


p3.

I prefer to fields to be private in almost all cases.


should be:

I prefer fields to be private in almost all cases.


p3.

I’m not going to go into all the benefits (and pitfalls) of immutability here, but there are many reasons why we might want our Point class to be immutable.


The Point class should be in fixed font.

p.4.

But what if you want to initialize a property as if it were a field?


Silly question but why would we want to do this when we can use a field?

p4.

You could only assign to an automatically implemented property in a constructor after chaining to another constructor, due to the rules about definite assignment, described below.



I haven’t heard of definite assignment before. Is this a language or compiler constraint? I would be keen to know more about this as it is being used in the examples, or even a brief explanation on what it is and why it exists. Now as I’m reading the next few paragraphs I’m wanting to know what definite assignment is and not concentrating on the example. I understand it’s a fine balance though as to explain it too much may detract from the point of the example but even a brief understanding would be useful.

p8.

You’re allowed to read an automatically implemented property before other fields are initialized, so long as you’ve set it beforehand.


It would be interesting to know why this restriction was in place and any affect on performance/memory it has since being lifted. Or was it just a reassigning of automatically implemented properties from methods to fields in MSIL when compiling somehow?

p9.

We’ll start off with properties at we’ve already been looking at them in the previous section, and then see how the same idea can be applied to other function members.


should be as, not at:

We’ll start off with properties as we’ve already been looking at them in the previous section, and then see how the same idea can be applied to other function members.


p9.

Figure 6.1 shows the same property, but annotated to highlight the useful parts, with the ceremony (braces, a return statement and a semi-colon) in a lighter shade.


i like the diagram (diagrams are good!) but this sentence could be a footnote or a title to the diagram.

p11.

I'll use Noda Time, my date and time library.


This is first introduced here but is referenced earlier (p8.) - This may be introduced in previous chapters, however. I only have access from chapter 6 onward.

p11.

The frequent uses of Noda Time for examples in the book aren’t trying to persuade you to use it. Obviously you should... but that’s a topic for a different day.


This footnote, although jovial and friendly isn’t necessary. You as the author have every right to promote/reference your other works.

p13.

For example, a simple Add method and its operator equivalent to add a Vector (with obvious X and Y properties) to a Point might look like listing 6.8 in C# 5.


This should be listing 6.15, not 6.8

p14/15.

? Static constructors
? Finalizers
?? Instance constructors?
? Read/write or write-only properties
? Read/write or write-only indexers?
? Events


This would be good as a table - especially highlighting the difference between read/write, read-only and write-only (although straight after it is explained they are lifted in C# 7, so may not be as important). However, what is the syntax for a write-only property or indexer?

p16.

I expect this to be reasonably common in the future. Setters tend to have validation, whereas getters are usually trivial in my experience.


You’d be surprised the amount of logic I’ve seen thrown into a getter on numerous occasions. Could this sentence possibly reinforce that it is bad practice to use a getter for anything more trivial than returning a value?

p16.

So with all the benefits to expression-bodied members, are there any downsides?


minor, but could be ‘with all the benefits of expression-bodied …’

p16.

it feels like I'm doing functional programming to a greater extent than before.


I was thinking this as reading the examples too - could possibly put in a note about Microsoft’s direction with the language to being more functional, etc. (if possible)

p16.

In some cases you really can’t use expression-bodied members, because your code includes a for statement or something like that.


Could use a linq .ForEach() loop though I would assume. This may put some users off using expression-bodied members.
Also, '... or something like that' doesn't sound very grammatically correct. Could possibly use '... or something similar'

p17.

As an example of the first of these, I have a class called Preconditions with a generic CheckNotNull method, accepting a reference and a parameter name. If the reference is null, it throws an ArgumentNullException using the parameter name; otherwise it returns the value. This allows a convenient combination of “check and assign” statements in constructors and the like. It also allows – but certainly doesn’t force – you to use the result as both the target of a method call, or indeed an argument to it. The problem is, it gets really hard to understand what’s going on if you’re not careful. Here’s a method from the LocalDateTime struct I described earlier:


This paragraph is a bit too long and is slightly confusing to understand the CheckNotNull class - could possibly use a small prototypal example of the class and/or broken into smaller paragraphs.

p17/18.

For explanatory variables, the NanosecondOfSecond example I provided earlier is just one of many properties on LocalTime.


There should be a line break before this sentence to separate the ideas and possibly sub-headings as I sort of forgot the purpose of the example when reading the second example. It would be useful to summarise the intent behind each of the examples as well so that the reader at a glance can understand why the guidelines are useful. eg.

- Use expression-bodied members for performing precondition checks
- Don’t use expression-bodied members for explanatory variables

This way the guidelines are clear, crisp and concise to the reader.

The examples are also slightly confusing as the first goes from good to bad use and the second goes from bad to good use - this should be consistent when analysing differences - I suggest bad then good, although if the main point is to highlight when and when not to use then the current order mixed order is ok, just needs to be highlighted more that this is the intention.

Again, the code achieves exactly the same goal... but in the original version, the minuteOfDay variable adds information about the meaning of the subexpression, making the code easier to read


Now I’m a bit confused as I thought the second example of the second guideline was actually easier to read. In that case, the heading should be an antithesis along the lines of 'When not to use expression-bodied members'

I’ll leave the above comments as is as it’s just my thoughts as I go though the doc.





jon.skeet (483) [Avatar] Offline
#2
Thanks - I'll look through all of these when I do a next sweep through all the reported errors and suggested changes.
(And yes, one post per chapter would be useful.)

If there are any areas you'd particularly want feedback on, please indicate that. Otherwise I'll just treat each one as a suggestion that I can accept/reject/modify as my editor and I see fit - is that okay?
434457 (10) [Avatar] Offline
#3
Yep, that's good with me. smilie