tag:blogger.com,1999:blog-72375308251913906982024-03-11T18:45:53.403+11:00Software DevelopmentLooking at trends in languages (particularly Go), methodologies (agile), software design, testing, etc.Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.comBlogger68125tag:blogger.com,1999:blog-7237530825191390698.post-88715294464293795822020-11-08T20:33:00.006+11:002020-11-08T22:43:43.569+11:00Rangeset - Go Generic Set<p>
Last month I introduced you to generics in Go. This time I discuss
a useful and substantial generic container that I created, and my experiences
using the <b>go2go </b>tool to write and test it.
</p>
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 195px;">
<p><b>What about generic chans?</b></p>
<p>
Last month I also mentioned generic chans and some potential cool uses.
</p>
<p>
Sorry, but first I want to discuss the rangeset package which has been
working for a while now.
</p>
<p>
I'll talk about a generic channels package I'm working on very soon -
<i>promise!</i>
</p>
</div>
<p>
This container I called <b><i>rangeset</i></b>. It contains a <b>Set</b> type similar to the one in the <a href="https://go.googlesource.com/go/+/refs/heads/dev.go2go/src/cmd/go2go/testdata/go2path/src/sets/sets.go2" target="_blank"><span style="color: #2b00fe;">go2go example set package</span></a>
but with some interesting properties and performance advantages.
</p>
<p>
Its main advantage is that it can save huge amounts of memory for sets that
have a large number of contiguous elements, and can be faster too. It
will regurgitate elements in order, unlike sets based on hash tables.
You can also invert a set and create the Universal set unlike any other Go set
implementations I have seen.
</p>
<h1 style="text-align: left;">
<span style="color: #3d85c6;">Introduction</span>
</h1>
<p>
I first created a primitive type of "range" set in C many decades ago and
found it useful in many scenarios. With the addition of templates (and
STL) to C++ I created a complete STL compatible class. Many people found
it very useful as it had much better performance (esp. memory usage)
characteristics than the C++ std::set for may common types of sets.
</p>
<p>
Sets are typically implemented as a balanced binary tree (eg: C++ std::set) or
a hash table (eg: C++ std:unordered_set). An important aspect of sets is
how fast you can check if an element is in a set and balanced trees have a
lookup time of O(log(n)) whereas hash tables are O(1). In practice, I
have found balanced trees are adequate (since O(log) is not too bad) unless
you have very large sets. They also have the advantage that you can
"iterate" the elements in order which you can't do with a hash table (without
additional complications like a separate index).
</p>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">“lookup time ...<br />is O(log(r))”</span>
</div>
<p>
A range set takes a different approach that makes it useful for sets with
large numbers of elements that are all in one or a few contiguous ranges.
Internally it uses a list of ranges, where each range is simply the first and
(one past) the end of a contiguous span of elements. In my original C++
version of rangeset I used a linked-list of ranges. In the Go version I
completely rewrote it to use a slice.
</p>
<p>
The lookup time for a range set is O(log(r)), where r is the number of
contiguous ranges. In the worst case (where no elements are next to any
other elements) the lookup time is no better than a balanced tree, or
O(log(n)), where n is the number of elements. But in the best case (where all
elements are in a single range) it is O(1) the same as a hash table.
</p>
<p>
Space performance is more interesting. In the worst case it is O(n) which is
still better than a binary tree or a hash table. In the best case it is
O(1). In fact, storing the universal set (the set of all elements)
requires a tiny amount of memory -- just one range.
</p>
<p>
It's important to remember that you need to know something of the likely
distribution of elements -- it's only useful for large sets if the elements
tend to clump together. For example, the set of all prime numbers (which
only has one contiguous range, ie: 2-3) is counter-indicated, but a good fit
would be something like a set containing all numbers with a leading decimal
digit "2" (ie: 2,20-29,200-299,2000-2999,...). It turns out that there are
many real-world scenarios where a range set is useful.
</p>
<p>
One final thing to note is that the element type of the Go
<b><span style="color: #b45f06;">rangeset.Set</span></b> type is constrained
to be an integer type (<span style="color: #b45f06;">byte, uint, int64</span>,
etc). Like a balanced tree the elements <i>must</i> be orderable - ie
support comparison using less than (<) etc. (A hash table based set only
requires the elements to be comparable - ie support the
<b><span style="color: #b45f06;">==</span></b> and
<b><span style="color: #b45f06;">!=</span></b> operations.) In theory a
range set could be created that allowed floating point or string elements but
I found that these are not useful in practice and I found it handy to be able
to increment values which is only supported by integer types.
</p>
<h1 style="text-align: left;">
<span style="color: #3d85c6;">Sets in Go (without Generics)</span>
</h1>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Maps as Sets </span>
</h3>
<p>
Traditionally sets in Go are implemented using a map with the map key type
being the set's element type and ignoring the map value. So for a set
of <b><span style="color: #b45f06;">int</span></b>s you would use a map with a key of
<b><span style="color: #b45f06;">int</span></b>. Perhaps the obvious value type for the map is a
<b><span style="color: #b45f06;">bool </span></b>(ie
<b><span style="color: #b45f06;">map[int]bool</span></b> for a set of ints),
but whether an element is in the set or not is better represented by the
presence of the key in the map so an "empty" value type is used. The empty
type conventionally used in Go is the empty struct, which uses no
memory. So a set of ints would be
<b><span style="color: #b45f06;">map[int]struct{}</span></b>.
</p>
<p>
When using a map as a set the set element type is restricted to types that are
comparable - ie types that can have<b><span style="color: #b45f06;"> == </span></b>and <b><span style="color: #b45f06;">!=</span></b> applied. Hence you
cannot have a set of slices, maps or funcs, since these types cannot be
compared (except to <b><span style="color: #b45f06;">nil</span></b>). Additionally, a type is not comparable if it is a struct, array or
interface that contains non-comparable component(s). (See my<span style="color: #2b00fe;">
<span><a href="https://devmethodologies.blogspot.com/2020/10/go-generics.html" target="_blank">previous post</a></span></span> for a full explanation of comparable types.)
</p>
<p>
Go's built-in map has no special support for sets so if you want to perform
set operations you have to write functions for the specific type of set you
are implementing. For example, you would need a function like this to find the
intersection of sets of strings:
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
func Intersect(set ...map[string]struct{}) map[string]struct{} {<br />
retval := make(map[string]struct{})<br /> if len(set) == 0
{ return retval }
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
<br />
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
outer:
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
for elt := range set[0] {
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
for _, other := range set[1:] {
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
if _, ok := other[elt]; !ok {
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
continue outer
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
retval[elt] = struct{}{} // found in all sets
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
return retval
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
}
</div>
<p>
Another deficiency of using a map is that the syntax is a little clumsier than
it would be with a set type built into the language (or a generic set).
Creating sets requires dealing with the unused empty struct as the map's value
type.
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
setA := StringSet{"a": {}, "b": {}, "c": {}}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
setB := StringSet{"c": {}, "d": {}, "e": {}}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
setC := StringSet{"e": {}, "a": {}, "c": {}}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
log.Println(Intersect(setA, setB, setC)) // {"c"}
</div>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Open Source Set Packages</span>
</h3>
<p>
Recognizing the problems with using the built-in map type to implement sets,
there have been several open-source packages created (such as the excellent
<a href="https://github.com/deckarep/golang-set" target="_blank"><span style="color: #2b00fe;">golang-set</span></a>). These provide methods which allow all manner of set operations such as
union, intersection, comparison (for equality), and some I don't even
understand like Cartesian product.
</p>
<p>
But since Go does not (yet) have parametric polymorphism, they must use
interfaces for polymorphism. This means internally they use a map
something like this:
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
type set map[<b>interface{}</b>]struct{}<br />
</div>
<p>
The problem with storing the elements in an interface is that you lose
compile-time type saftey. For example, it would be easy to accidentally add an
integer to a set of strings and you could only discover the problem at
run-time using type assertions. You could even add a value of a non-comparable
type to a set which would cause a run-time panic.
</p>
<p>
Furthermore, it also affects performance since set elements must be "boxed"
and "unboxed" as they are stored in an
<span style="color: #bf9000;"><b>interface{}</b></span>.
</p>
<h1 style="text-align: left;">
<span style="color: #3d85c6;">Sets using Generics</span>
</h1>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Go Authors sets package</span>
</h3>
<p>
Generics allow the above-mentioned problems with using sets in Go to be
addressed (without the need for another built-in type). Undoubtedly,
when Go has generics, sets will be one of the first things added to the Go
standard library. In fact the "dev.gog2go" branch of the Go compiler
repository includes a "proposed" implementation of exactly that in a
<a href="https://go.googlesource.com/go/+/refs/heads/dev.go2go/src/cmd/go2go/testdata/go2path/src/sets/sets.go2" target="_blank"><span style="color: #2b00fe;"><b>sets</b> package</span></a>.
</p>
<p>
Internally this <b><i>sets</i></b> package uses a map (see
<a href="https://go.googlesource.com/go/+/refs/heads/dev.go2go/src/cmd/go2go/testdata/go2path/src/sets/sets.go2#10" target="_blank"><span style="color: #2b00fe;">sets.go2 line 10</span></a>) to implement a generic set. It has the safety and performance of a
map with convenience and reliability of tried and tested methods. There are
basic methods (create a set, copy a set, compare sets, add/delete elements,
size of the set, etc) and set operations (union, intersection, subset, etc)
</p>
<p>
There are also some useful methods to get or filter the elements of the set.
But note that, since the elements are stored in a map, the order the elements
are processed/filtered is indeterminate.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">C++ range_set</span>
</h3>
<p>
I first became familiar with parametric polymorphism when "templates" were
added to C++. I was particularly enamored with STL library originally
designed by Alex Stepanov, and later incorporated into the C++ standard
library. I won't go into all the wonderful details but one of the most
useful things it provided was containers (vectors, lists, deques, maps, sets,
etc).
</p>
<p>
My first experiment with C++ templates was to create a "range" set which was
drop-in compatible with the STL set class, apart from the fact that the
element type had to be an integer type. (Technically it could be any type that
implemented operator<() and operator++() which would include integers, and
possibly, other user-defined types.) Internally it was implemented using
a linked-list of range structs rather than the balanced binary tree used by
the STL set class.
</p>
<p>
If you are interested, the full source code (C++ header file) can be found
<a href="https://github.com/AndrewWPhillips/HexEdit/blob/master/HexEdit/range_set.h" target="_blank"><span style="color: #2b00fe;">here</span></a>. I also wrote an article for the C/C++ User Journal in June 1999 that
describes it (see
<span style="color: #2b00fe;"><a href="https://www.drdobbs.com/a-container-for-a-set-of-ranges/184403660" target="_blank"><span style="color: #2b00fe;">A Container for a Set of Ranges</span></a>)</span>.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Go rangeset package</span></h3>
<p>
A few months ago I decided to try implementing a generic range set class in Go
using the experimental go2go tool. Although my C++ implementation used a
linked list of ranges, I found that in Go a slice of ranges worked as well if
not better. Each "range" simply stores the bounds of the range using
asymmetric bounds (inclusive lower bound, exclusive upper bound). All
operations maintain the property that the ranges are kept in numeric order and
non-overlapping.
</p>
<p>
Like my C++ range set, the Go implementation tries to be compatible with Go
authors sets package mentioned above. I have used the same method names,
including <b><span style="color: #b45f06;">Contains</span></b>, <b><span style="color: #b45f06;">AddSet</span></b>, <b><span style="color: #b45f06;">SubSet</span></b>, <b><span style="color: #b45f06;">Iterate</span></b>, etc, so a rangeset could act as a drop-in replacement. Of course,
there are additional methods that take advantage of the unique properties of a
rangeset, such as the ability to return all the ranges. And as I've
already mentioned there is a limitation that the element type must be an
integer type.
</p>
<p>
Here is a simple example. (For a complete list of methods and functions
see the
<a href="https://github.com/AndrewWPhillips/rangeset/blob/master/README.md" target="_blank"><span style="color: #2b00fe;">README </span></a>file.)
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
var squares, evens rangeset.Set[int]
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
for i := 1; i <= 12; i++ {
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
squares.Add(i * i)
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
for i := 2; i < 1000; i += 2 {
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
evens.Add(i)
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
}
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
<br />
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
// Find all the even squares
</div>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
fmt.Println(Intersect(squares, evens)) <span style="font-size: x-small;">// {4,16,36,64,100,144}
</span></div>
<h1><span style="color: #3d85c6;">Rangeset Implementation</span></h1>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Using the go2go Tool</span>
</h3>
<span><p style="text-align: left;">
I developed the rangeset package using the <i>go2go </i>tool. It is an amazing tool with very complete support for what
I think Go generics will look like. In essence it
translates .go2 source files (containing generics types/functions) into .go
files which can then be built as normal.
</p>
<p style="text-align: left;">
It does have a few minor deficiencies such as no ability to do
conditional compilation (build tags). It has very good support for
tests, except that it does not support external tests, though that may
be fixed by the time you read this. (Note that rangeset has a lot of
tests as I discuss below).
</p>
<p style="text-align: left;">
There are many places you can find detailed steps on how to install and
use the go2go tool but in brief you need to have a recent Go compiler
and git installed, then clone the latest Go repo and build the dev.go2go
branch. Then you can just run
</p>
<p style="text-align: left;">
<span style="font-size: medium;"><b>$ go tool go2go build</b></span>
</p>
<p style="text-align: left;">
to translate .go2 file to .go and invoke the Go compiler to complete
the build of the package.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Spans</span></h3>
<p style="text-align: left;">
Internally, a set in the rangeset package (<span style="color: #b45f06;">rangeset.Set</span>) uses a slice where each element is a
<span style="color: #b45f06;">struct </span>containing the start and end
elements of a range. Essentially it is just:
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace; text-align: left;">
type Set[T constraints.Integer] []struct{bottom, top T}
</div>
<p style="text-align: left;">
Note that <span style="color: #b45f06;">constraints.Integer</span> is
a constraint defined in the constraints package that just specifies
all of Go's integer types.
</p>
<p style="text-align: left;">
In years of using my C++ rangeset class I found it occasionally useful
to have access to the actual ranges, so I created a separate type for
this. I called this type <span style="color: #b45f06;">Span</span> to avoid confusion with other uses of the word range and to avoid
conflict with Go's
<span style="color: #b45f06;">range</span> keyword.
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace; text-align: left;">
type Span[T constraints.Integer] struct{bottom, top T}
</div>
<p style="text-align: left;">
There is a <span style="color: #b45f06;">Spans()</span> method that returns all the ranges in the set as a slice of
<span style="color: #b45f06;">Span[T]</span>. You can also
quickly add a range of values to a rangeset using the <span style="color: #b45f06;">AddRange()</span> method. Of course, internally Spans are merged and split as
necessary to maintain a normalized layout, which is the most efficient
and allows operations such as comparing sets for equality.
Interestingly this means that adding an element to a rangeset can
reduce its memory usage if the new element is the missing value
between two existing ranges, causing them to be joined.
</p>
<p style="text-align: left;">
See for the actual
<a href="https://github.com/AndrewWPhillips/rangeset/blob/master/basic.go2#L10-L15" target="_blank"><span style="color: #2b00fe;">code defining these types</span></a>.
</p>
<p style="text-align: left;">
It's also important to note that ranges are specified (and stored
internally in Spans) using <a href="https://devmethodologies.blogspot.com/2012/12/asymmetric-bounds-and-zero-based.html]" target="_blank"><span style="color: #2b00fe;">asymmetric bounds</span></a>. A counter-note is that when a set is serialized to a string
the ranges are encoded using inclusive bounds; this avoids confusion
to users who may be exposed to these strings.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Number of Elements</span>
</h3>
<p style="text-align: left;">
To be compatible with the Go Authors set,
<span style="color: #b45f06;">rangeset.Set</span> implements a<span style="color: #b45f06;">
Len() </span>method. The problem with this method is that it returns an
<span style="color: #b45f06;">int </span>but, depending on the element
type, the number of elements can easily exceed the maximum
<span style="color: #b45f06;">int</span> value. For example, in Go
implementations where an <span style="color: #b45f06;">int </span>is 32
bits then
<span style="color: #b45f06;">uint, uint32, int64, uint64</span>, and
<span style="color: #b45f06;">uintpr</span> can have sets with more
elements than the maximum <span style="color: #b45f06;">int</span>. (In the Go Authors set this is not typically a problem as you
run out of memory before you can have a set that big.) Even a the
set of all <span style="color: #b45f06;">int </span>or
<span style="color: #b45f06;">int32 </span>(ie,<span style="color: #b45f06;">
rangeset.Universal[int]()</span>) has one more element than can be represented in an
<span style="color: #b45f06;">int</span>! In these cases the
<span style="color: #b45f06;">Len()</span> method will silently
overflow, since for compatibility it can't return an error.
</p>
<p style="text-align: left;">
If this can possibly occur then you need to use the
<span style="color: #b45f06;">Length()</span> method instead. This
returns two values -- the number of elements (as
<span style="color: #b45f06;">uint64</span>) and the number of ranges in
the set. Note that even using a
<span style="color: #b45f06;">uint64</span> for the length the
number of elements in a universal set of
<span style="color: #b45f06;">int64</span>,
<span style="color: #b45f06;">uint64 </span>(and possibly
<span style="color: #b45f06;">int</span>,
<span style="color: #b45f06;">uint </span>and
<span style="color: #b45f06;">uintptr</span>) is one more than the
maximum <span style="color: #b45f06;">uint64</span> - in this case you
also need to check the number of ranges. That is, if both values
returned from<span style="color: #b45f06;"> rangeset.Length() </span>are
zero then you have an empty set, but if length == 0 and number of ranges
== 1 then you have a universal set.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Set Operations</span>
</h3>
<p style="text-align: left;">
There are simple methods to add or delete elements (or ranges of
elements) and check for the presence of an element in a set. There are also methods to perform set operations such as
<span style="color: #b45f06;">Intersect()</span>
which find the set intersection of a set with another set.
Similarly, the <span style="color: #b45f06;">AddSet()</span>
method performs a set union, and <span style="color: #b45f06;">SubSet()</span>
performs a set difference operation.
</p>
<p style="text-align: left;">
There are also functions that take a variable number of sets as
parameters and return things like the union, intersection or whether
they are all equal. I may later add other fancy set operations like power-sets and
Cartesian products if there is demand for it.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">The Complement operation and Universal Set</span>
</h3>
<p style="text-align: left;">
The <span style="color: #b45f06;">Complement()</span>
method returns the inverse of a set - that is, any element in the set is
removed and any element not in the set is added. This operation is
fast, only taking time proportional to the number of ranges -
O(r). The complement of the empty set is the universal set (and
vice versa).
</p>
<p style="text-align: left;">
The function rangeset.Universal[T]() returns a Universal set - that is,
as set that contains all elements possible for its element type.
It's faster than taking the complement of an empty set.
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Serialization and Deserialization</span>
</h3>
<p style="text-align: left;">
The <span style="color: #b45f06;">String()</span> method encodes a range set as a string; the <span style="color: #b45f06;">NewFromString()</span>
function does the opposite converting an encoded string to a set. These
are useful for serializing sets for transmission or storage, but can
also be handy for seeing or even entering sets.
</p>
<p style="text-align: left;">
The format of the string is that the set is always enclosed in braces
(<span style="color: #b45f06;">{}</span>) and elements or ranges are
separated by a comma (,), while a range is two numbers separated by a
colon (:). For example:<span style="color: #b45f06;">
"{1,3,5:9}" </span>encodes a set of 7 elements. Note that to make it easier for users to
deal with these string they use "inclusive" bounds (unlike how they are
represented normally using asymmetric bounds as discussed above), so the
string <span style="color: #b45f06;">"{1:10}"</span> represents ten
elements (1 to 10 inclusive).
</p>
<p style="text-align: left;">
The string produced by the <span style="color: #b45f06;">String()</span> method is normalized - ie, elements and ranges are in order and
not overlapping, but this is not a requirement of the string passed to <span style="color: #b45f06;">NewFromString()</span>. Plus, the special element "E" represent the end, or very first/last
element of a set, so this code produces a set with the elements 1 and 99
to 255 inclusive:
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace; text-align: left;">
rangeset.NewFromString[uint8]("{99:E,1}")
</div>
<p style="text-align: left;">
Furthermore the shortcut <span style="color: #b45f06;">"{U}"</span> means the universal set - the
same as<span style="color: #b45f06;"> "{E:E}"</span>.
</p>
<h3 style="text-align: left;"><span style="color: #3d85c6;">Obtaining and Processing All Elements</span></h3>
<p style="text-align: left;">
<span style="font-weight: 400;">Like the Go Authors set, a rangeset has a method to return all elements
as a slice (called </span><span><span style="color: #b45f06;">Values()</span></span><span style="font-weight: 400;">), but be careful as this could produce a huge slice if there are any
large ranges. There is also a </span><span><span style="color: #b45f06;">Spans()</span></span><span style="font-weight: 400;"> method that returns all the ranges as a slice of Spans, which may
be safer.</span>
</p>
<p style="text-align: left;">
<span style="font-weight: 400;">Also like the Go Authors set, there is a method (called Iterate()) that
can be used to run a function on every method in the set. Also
`Filter()` can be used to selectively delete elements from the
set.</span>
</p>
<p style="text-align: left;">
<span style="font-weight: 400;"><i>Unlike </i>the Go Authors set, there are also methods to handle
channels of elements. </span><span><span style="color: #b45f06;">Iterator()</span></span><span><span style="font-weight: 400;"> (not to be confused with </span><span style="color: #b45f06; font-weight: 400;">Iterate()</span><span style="font-weight: 400;"> mentioned above) returns a </span><span style="color: #b45f06; font-weight: 400;">chan</span><span style="font-weight: 400;">
that receives all the elements in order. In contrast, </span><span style="color: #b45f06;">ReadAll()</span><span style="font-weight: 400;">
adds all items it receives on a channel to the set. Both of
these methods take a
<span style="color: #b45f06;">context.Context</span> as their first
parameter so they can be cancelled at any time, or after a specified
timeout.</span></span>
</p>
<h3 style="text-align: left;">
<span style="color: #3d85c6;">Testing</span>
</h3>
<p style="text-align: left;">
The rangeset package has about 20 table-driven and 20 non-table
driven test functions. In all there are about 700 tests with
100% code coverage. I believe that every boundary condition and possibility is
tested, but please tell me if you spot a gap anywhere.
</p>
<p style="text-align: left;">
<span style="font-weight: 400;">Note that currently all the tests are internal tests since I could not
get external test (using package
<span style="color: #b45f06;">rangeset_test</span>) to work.
However, all the tests are "external" tests - ie only test the public
API of the package. I will convert the tests to external tests
when possible.</span>
</p>
<p style="text-align: left;">
<span style="font-weight: 400;">To run all the tests:</span>
</p>
<p style="text-align: left;">
<span style="font-size: medium;"><b>$ go tool go2go test</b></span>
</p>
<h1 style="color: #3d85c6; text-align: left;">Conclusion</h1>
<p style="text-align: left;">
A rangeset is not appropriate for every type of set. It has some
performance advantages for sets with large ranges of contiguous
elements. In fact very large sets can be implemented in a small amount
of memory which would be impossible with other types of sets, such as sets
with trillions of elements.
</p>
<p style="text-align: left;">
Many operations, such as adding, deleting and finding elements, use a binary
search on the list of ranges. In the worst case (where few or no
elements are contiguous) this gives time complexity of O(log) but in the best
case (all elements are in a single contiguous range) the time complexity of
O(1), like other set implementations. In practice it can have better
performance than even a hash table.
</p>
<p style="text-align: left;">
Unlike hash table based sets, when the elements are iterated (or otherwise
processed) they are seen in order. An unusual and sometimes useful feature is
the ability to invert a set and even create a universal set (inverse of the
empty set).
</p>
<p style="text-align: left;">
Another cool feature is the ability to send/receive sets to/from a
<span style="color: #b45f06;">chan</span>. The
<b><span style="color: #b45f06;">Iterator()</span></b> method returns a (generic)
<span style="color: #b45f06;">chan</span> that returns all the elements of the
set (in order); the <b><span style="color: #b45f06;">ReadAll()</span></b> method adds new elements to a set by reading from a chan. These
channels can be used with a <b>generic channels package</b> I am currently
working on which I will talk about next time!
</p>
<p style="text-align: left;"><br /></p>
</span>Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-73701843972821283292020-10-18T20:52:00.002+11:002023-05-04T18:55:46.023+10:00Go Generics<p>
<span style="font-size: medium;">There's been a lot written about <i>generics </i>in Go as they get closer
to graduating into the language. I just want to talk about a few
important things that I've not seen discussed elsewhere. In
particular:</span>
</p>
<p></p>
<ul style="text-align: left;">
<li>
<span style="font-size: medium;">what parametric polymorphism actually is</span>
</li>
<li>
<span style="font-size: medium;">why Go does not especially need it, but can benefit from it</span></li>
<li><span style="font-size: medium;">C++ templates, and why Go doesn't need all that</span>
</li>
<li>
<span style="font-size: medium;">latest proposed syntax (I'll update this post if/as it changes)</span>
</li>
<li><span style="font-size: medium;">the importance of constraints</span></li>
<li>
<span style="font-size: medium;">performance - of builds and generated code</span>
</li>
<li>
<span style="font-size: medium;">how to try generics with the go2go tool or <a href="https://go2goplay.golang.org/" target="_blank"><span style="color: #2b00fe;">go2go playground</span></a></span>
</li>
<li>
<span style="font-size: medium;">how generic channels may be a game changer</span>
</li>
</ul>
<p></p>
<p>
<span style="font-size: medium;">But first an introduction if you know nothing about it...</span></p>
<p>
<b><span style="color: #3d85c6; font-size: x-large;">Parametric Polymorphism</span></b>
</p>
<p>
<span style="font-size: medium;">As Rob Pike keeps reminding us, what is commonly called generics is
technically parametric polymorphism. But even he admitted (when he talked at
the
<a href="https://www.meetup.com/golang-syd/events/266746397/" target="_blank"><span style="color: #2b00fe;">Sydney Go Meetup last December</span></a>) after saying "parametric polymorphism" many times, and stumbling on the
words at least once, that <b><i>generics</i></b> is less of a mouthful. Personally I don't like the word either but it
seems that <i>generics </i>is now the <i>de facto</i>, even official,
name so I am going to stick with it. And, though not exactly the same, it is
similar to what are often referred to as <i>generics</i> in other
languages like C#, Java, etc, which I think is helpful for new Gophers.</span>
</p>
<p>
<span style="font-size: medium;">So what is it? To simplify, there are two basic forms allowing you to
specify <i><b>type parameters</b></i> either on a <b>function</b> or on a <b>type</b>. These are "compile time" not "run time" parameters as they evaluated and used by the compiler as it works.<br /><br />Note that every
programming language ever invented has <i>generics</i> built into the
language. For example, Fortran (the first high-level language) had
these built-in:</span>
</p>
<p></p>
<ul style="text-align: left;">
<li>
<span style="font-size: medium;">arrays - a generic type where the type of the element(s) is the type
parameter</span>
</li>
<li>
<span style="font-size: medium;">min - a generic function where the type parameter is implied by the type
of the parameter(s)</span>
</li>
</ul><div><span style="font-size: medium;">Similarly Go already has built-in generic types (arrays, maps, slices) and functions (eg <span style="color: #b45f06;">copy()</span> which can work with any type of slice). Generally, when we talk about <i>generics</i> in a language we are usually talking about the "user-defined" types and functions. Go does not (yet) have this which is why you can't write a function that does what <span style="color: #b45f06;">copy()</span> does.</span></div>
<p></p>
<p>
<b><span style="color: #3d85c6; font-size: large;">Function example</span></b>
</p>
<p>
<span style="font-size: medium;">Here is a "user-defined" generic function in (the proposed new) Go, that prints the type of it's type
parameter:</span>
</p>
<div class="cccc" style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">
func f[T any]() {<br /> var v T // declare dummy variable of the type<br /> fmt.Printf("%T\n", v)<br />
}
</div>
<p>
<span style="font-size: medium;">where the function <span style="color: #e69138;">f </span>has one type
parameter <span style="color: #e69138;">T</span> [in square brackets] and
no normal parameters (in round brackets). <span style="color: #e69138;">
T</span>
is followed by the constraint <span style="color: #b45f06;">any</span><span style="color: #e69138;"> </span>which means that the type parameter
can be of any type at all. We can call the function like this:</span>
</p>
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">func main() {<div> f[int]() // type parameter T is int</div><div>}</div></div>
<p>
<span style="color: #3d85c6; font-size: large;"><b>Type example</b></span>
</p>
<p><span style="font-size: medium;">Here is a generic type:</span></p>
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">type Pair[T1, T2 any] struct { first T1; second T2 }</div><p><span style="font-size: medium;">where the <span style="color: #b45f06;">Pair</span> type has two type
parameters, <span style="color: #b45f06;">T1</span> and
<span style="color: #b45f06;">T2</span>, used for struct fields which may be of any (unrelated) types.</span></p>
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">func main() {<div> v := Pair[float64, string]{ 0, "abc"}</div><div> point := Pair[int, int]{ 1, 2 }</div><div> fmt.Printf("%v %v\n", v, point)</div>}</div>
<p>
<span style="color: #3d85c6; font-size: x-large;"><b>Does Go Need Generics?</b></span>
</p>
<p>
<span style="font-size: medium;"><span>This has been a big ongoing debate and I think that the Go community is
finally leaning towards <b><i>yes</i></b>. People, who have used <i>generics </i>in other languages and
have read about Go or only superficially tried it, are usually incredulous
that Go does not have generics (myself included a few years ago).
However, it has managed to get by without them for a long time so let's look
at how and why.</span>
</span></p>
<p>
<span style="font-size: medium;"><span>One rarely discussed reluctance for adding generics to Go is the concern that build times will be reduced. Some may scoff but part of the joy of Go
is the quick builds. In 2009 Russ Cox gave a
<a href="https://research.swtch.com/generic" target="_blank"><span style="color: #2b00fe;">convincing argument</span></a> but the go2go tool seems to be pretty quick (see benchmarks later). My hope <i>and firm belief</i> is that when generics are added to the
compiler proper, it will have negligible effect on compile times, at least
for code that does not use generics.</span>
</span></p>
<p>
<span style="font-size: medium;"><span>Another argument for not adding generics to Go is that the inbuilt
facilities are sufficient. I agree with this. Though enamoured with
C++ templates, especially the STL, in all honesty 97% of what I used the STL
for in C++ can be achieved just as nicely in Go using slices and maps.
I'd even say that I make much more use of the in-built generic maps in Go
than I ever did with the analogous C++ containers (std::map/set/unordered_map/multimap, et al).</span>
</span></p>
<p>
<span style="font-size: medium;"><span>Another point is that the Go community is far more tolerant of duplicated
code. It's OK to have two functions with similar code - eg, one for
<span style="color: #b45f06;">int</span>s and another for
<span style="color: #b45f06;">string</span>s.
<a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank"><span style="color: #2b00fe;">DRY</span></a> is good but some repetition can be tolerated.</span>
</span></p>
<p>
<span style="font-size: medium;"><span>A final argument for not having generics is that you can use </span><b>go:generate</b><span>
to run tools to convert some form of generic code into Go code. Sure you can
do this but it is a bit tedious and "non-standard". I don't really buy this
one.</span>
</span></p>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 256px;"><span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">“use of </span><span style="color: #b45f06; font-family: Georgia, Times New Roman, serif; font-size: large;">interface{}</span><span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;"> ...<br />affects performance<br />and type safety”</span></div>
<p>
<span style="font-size: medium;"><span>On balance this lead me (and I think the Go community) to conclude that we
can probably get by without generics. On the other hand, there has
always been <b>one thing that grates with me</b> - the use of
<span style="color: #b45f06;">interface{}</span> with containers and algorithms as the "poor
mans" alternative to generics (for example, the <a href="https://golang.org/pkg/container/list/" target="_blank">linked list package from the Go standard library</a>, which I have never heard of anyone liking or using). </span><span>This affects performance due to boxing/unboxing (admittedly not always
important) and type safety (always important unless you like Python or Javascript).</span>
</span></p>
<p><span style="font-size: medium;"><span>Generics will be useful for things like adding generic containers not
already built into the language. B</span><span>ut there is one killer reason Go should have generics - type-parameters on <span style="color: #b45f06;">chan</span>s allow creation of some very useful facilities. More on this soon!</span></span>
</p>
<p>
<b><span style="color: #3d85c6; font-size: x-large;">C++ Templates vs Go Generics</span></b>
</p>
<p>
<span style="font-size: medium;"><span>Before we go further, I want to talk about C++ templates. If that's not what <i>you</i> want, then you
can skip this section. It may be useful background to see
what C++ templates have that Go generics don't have.</span>
</span></p>
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 256px;"><div style="text-align: center;"><b>Contracts, constraints, concepts</b></div><b><div style="text-align: center;"><b>Is it all a con?</b></div></b><div style="text-align: center;"><br /></div>
Constraints allow the creator of a generic type/function to say what capabilities a type must have to be used as the type parameter. For example, a <span style="color: #b45f06;">Min()</span> function makes no sense for a type that has no inherent ordering.<br /><br />
I was a bit dubious about the point of constraints at first. Why not just let the compiler work out if a type is unsuitable when it goes to use it. For example, <span style="color: #b45f06;">Min()</span> would need to use the less than operator, so the compiler would be able to detect the problem when you try to take the minimum of two structs because structs can't be compared for order (in Go).<br /><br />
However, there are some good reasons to have constraints in Go (or any language) as I discuss below.
</div>
<p>
<span style="font-size: medium;"><span>I should mention first the one thing that Go generics <i>will</i> have and
C++ doesn't have (yet) is <b><i>constraints</i></b>, as they are called in the latest design draft - see
<a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md" target="_blank"><span style="color: #2b00fe;">Type Parameters - Draft Design</span></a>. (Compilers implementing the new C++ 20 standard will have a similar thing called
<b><i>concepts</i></b>.)</span>
</span></p>
<p>
<span style="font-size: medium;"><span>Constraints (and the functionally similar </span><b><i>contracts</i></b><span> in earlier draft designs) have been the major sticking point for
implementing generics. I discuss the syntax and use of constraints in
detail later.</span>
</span></p>
<p><span style="font-size: medium;">Anyway, here's what C++ templates have that Go generics do not
have:</span>
</p>
<p><span style="color: #3d85c6; font-size: large;">Specialization</span></p>
<p>
<span style="font-size: medium;"><span><span>Sometimes you want a type parameter of a specific type to be handled
differently. For example, in C++ the STL provides the vector container
(called <span style="color: #b45f06;">vector<type T></span>). There is a specialization for <span style="color: #b45f06;">bool
</span> (called <span style="color: #b45f06;">vector<bool></span>) that is primarily intended to save space by cramming the elements 8 to a byte. This can save lots of memory for large
vectors over a non-specialised version that would use a byte per element. However, </span></span><span style="color: #b45f06;">vector<bool></span><span> is generally deprecated and rarely used.</span></span></p>
<p>
<span style="font-size: medium;"><span>C++ also supports "partial specialization" of a template that has more than one
type parameter. Without getting into the details - some type parameter(s) are specialized with special code that keeps some type parameter(s) "generalized".</span>
</span></p>
<p>
<span style="font-size: medium;">I don't believe we need these features in Go. Their usefulness is limited
and it just adds complexity (and increases build times).</span>
</p>
<p>
<span style="color: #3d85c6; font-size: large;">Member function templates</span>
</p>
<p>
<span style="font-size: medium;">Originally C++ allowed type parameters on functions and types, but you
could not add type parameters to methods of a class (called member function
templates in C++ parlance). However, it was found necessary and added soon
after. In Go, these would be called <b><i>generic methods</i></b> and here is an
example (not valid code):</span>
</p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type BoolStack []bool</span><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"><br /></span></div><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func (s *BoolStack) PushEqual[T comparable](v1, v2 T) { <span style="font-size: x-small;">// not valid</span></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> *s = append(*s, v1 == v2)</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="font-size: medium;">I have occasionally found generic methods useful in C++ but only on certain
large classes (which probably should have been avoided anyway). I'm not sure
adding generic methods would be useful in Go. Moreover, there is a simple
workaround - simply convert the method to a <b>function</b> like this.</span></p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func PushEqual[T comparable](s *BoolStack, v1, v2 T) {</span><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> *s = append(*s, v1 == v2)</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="font-size: large;">There is still the limitation with the workaround that a <span style="color: #b45f06;">func </span>cannot be used to allow a type to implement an <span style="color: #b45f06;">interface </span>the way that a method can. We will have to see if Go needs generic methods.</span></p><p><span style="font-size: medium;"><span>Note that this is often confused with using </span><span>a type parameter on a receiver of a generic
type. That <i>is </i>allowed and is particularly useful. For example:</span></span></p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type stack[T any] []T</span><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"><br /></span></div><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func (s *stack[T]) Top() T { <span style="font-size: x-small;">// OK: method receiver *can* be generic</span></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return (*s)[len(*s)-1]</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="color: #3d85c6; font-size: large;">Metaprogramming</span></p>
<p>
<span style="font-size: medium;"><span>C++ is famous for template metaprogramming -- there have been whole books
written about it. To explain what it is, remember that when the C++
compiler processes templates it essentially generates internal code for the
templates for each used "instantiation" of the type parameters. With
some bewildering (even by C++ standards) tricks the compiler can be induced
to create all manner of code at compile-time. Essentially you can
write source code that <i>generates</i> source code (at compile-time) to become part of
the resulting program.</span>
</span></p>
<p>
<span style="font-size: medium;"><span>What's the point? Well it can be used different things such as what
go:generate is used for. For example, many algorithms require pre-computed
values or tables. If you can't generate them during the build you could compute these values at
program startup, but for efficiency (ie to avoid delays when the software
starts running) it can be better to precompute the values and incorporate them
into the code. Before template meta-programming it was common in C++ to write code to
generate header files that are then incorporated into the build. Template
metaprogramming allows these sorts of things to be actually done by the
compiler at compile-time.</span>
</span></p>
<p>
<span style="font-size: medium;">There are some advantages to this, of course, such as the source code being
self-contained. However, it does complicate the compiler (and the code) with one consequence that builds become slower. For<b> Go</b> I think we
can safely say that nothing like this will ever be added to the language, where these
things are typically done at run-time (where the increased startup time is unimportant) or if necessary can be performed as part of the build, eg
using go:generate.</span>
</p>
<p>
<span style="color: #3d85c6; font-size: large;">Non-type Parameters</span>
</p>
<p>
<span style="font-size: medium;"><span>As well as type parameters, C++ also supports non-type template
parameters. This allows a constant value to be used in the
instantiation of a template. Why are they necessary? To see the point
consider the declaration of an array in Go. An array (as I said above)
is a generic type built into the language. In a declaration like
this:</span>
</span></p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> var a [4]int</span></div><p><span style="font-size: medium;"><span>we are declaring the array with two (compile-time) parameters. There
is the type parameter (</span><span style="color: #b45f06;">int</span><span>) which says we
want an array of integers. But there is also the non-type parameter (</span><span style="color: #e69138;">4</span><span>) which says that the array has 4
elements.</span></span></p>
<p>
<span style="font-size: medium;"><span>In certain situations non-type compile-time parameters can be very useful
in generic code (for example if arrays weren't built into Go). I would not be surprised if they were added to Go in the
future - at least integer constant parameters.</span></span></p><p><span style="font-size: medium;"><span>One thing I would like to be able to create is a generic computational geometry package in Go. For example, a <span style="color: #e69138;">Point</span> type would take a generic integer parameter for the number of dimensions, so a lot of code could be shared between 2-D and 3-D (etc) points.</span></span></p>
<p><span style="font-size: medium;">A workaround in Go, that could allow an integer generic parameter may be to use arrays, though you couldn't have an unlimited number of values as you would have to specify all the possible arrays sizes in the parameter's constraint.</span></p><div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type Sizer interface {</span></div><div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> type [0]int, [1]int, [2]int, [3]int <span style="font-size: x-small;">// only used for size</span><br /></span><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div><p><span style="font-size: medium;">[Ed 2021: the above is the old constraint syntax - here is what you need for Go 1.18+]</span></p><div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type Sizer interface {</span></div><div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> [0]int | [1]int | [2]int | [3]int <span style="font-size: x-small;">// only used for size</span><br /></span><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div><p><span style="font-size: medium;">You can try this now on the <a href="https://go2goplay.golang.org/p/iKYZFWcR7e3" target="_blank"><span style="color: #2b00fe;">go2go playground</span></a>. [Ed: try <a href="https://go.dev/play/p/1fHK0GN2l47">Go Playground</a>]</span></p><p><span style="color: #3d85c6; font-size: large;">Defaulted and Variadic Template Parameters</span></p><p><span style="font-size: medium;">C++ also supports default values for template parameters, if they are left out by the user of the template. It even supports variadic template parameters. Go does not support these sorts of things for normal (non-generic function) parameters, so it is unlikely to ever have these features.</span></p><div><b style="color: #3d85c6; font-size: xx-large;">Go Generics Syntax</b></div>
<p>
<span style="font-size: medium;">How exactly Go generics will work has been hugely debated especially after
the
<a href="https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md" target="_blank"><span style="color: #2b00fe;">2019 Draft Design</span></a>. It's been clear for awhile that generics will simply add type-parameters
to functions and types (and not have any of the bells and whistles of C++
that I mentioned above). But there were still a few unresolved issues -- how
to handle <b><i>constraints</i></b> plus the use of brackets and precise
syntax. I'll quickly explain the syntax then talk a bit more about the
important subject of constraints.</span>
</p>
<p>
<b><span style="color: #3d85c6; font-size: large;">Brackets</span></b>
</p>
<p>
<span style="font-size: medium;"><span>There has been too much debate about what sort of brackets are used to enclose
type parameters - round (parentheses), angle, square, chevrons or guillemets
(these are Unicode characters but that's OK since Go source code is UTF-8). The
obvious choice, and one I would have liked, would have been angle brackets (<>) but it turns out this creates crazy ambiguities in the language. Round
brackets were tried for a while but there were also ambiguities (with simple
but clunky workarounds). Currently, perhaps finally, square brackets
are being used and they work well enough.</span>
</span></p>
<p>
<span style="font-size: medium;">A closely related change has been the removal of the need for the
<span style="color: #b45f06;">type</span> keyword in a generic
declaration. So a generic function in the original Draft Design such
as this:</span>
</p>
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "Courier New", Courier, monospace;">func Print(type T)(s []T) { // 2019 syntax<br /></div>
<p><span style="font-size: medium;">is now written like this:</span></p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func Print[T any](s []T) { // current syntax</span></div>
<p><span style="font-size: medium;">Note that the <span style="color: #b45f06;">type </span>keyword is gone and
the round brackets have been replaced with square brackets. You might
also have spotted the addition of the word
<span style="color: #b45f06;">any</span> - this is a type constraint.
Previously if there were no constraints on the types allowed for a type
parameter then you could leave it out, but now you <i>must</i> provide a
constraint, where <span style="color: #b45f06;">any</span> obviously means
there's no constraint at all.</span></p>
<p><span style="font-size: medium;">Speaking of constraints...</span></p>
<p><b style="color: #3d85c6; font-size: x-large;">Constraints</b></p>
<p>
<span style="font-size: medium;"><span>Constraints allow you to say which types for a type parameter are
suitable. For example, in the
<span style="color: #b45f06;">Min[T]()</span> function already discussed it
should only be used with type parameter that supports the less than (<span style="color: #e69138;"><b><</b></span>) operation. How to handle constraints has probably been the most
contentious part of adding generics to Go in the last year and has resulted
in draft designs that (before this year) involved the
<span style="color: #b45f06;">contract</span> keyword. (I
contributed to the debate but I won't go into that history now.)</span>
</span></p>
<p>
<span style="font-size: medium;"><span>I'll just tell you how constraints work, including a few gotchas, in a
moment. First we need to understand why constraints are even needed (after
all C++ got by without them for decades).</span>
</span></p>
<p>
<span style="font-size: medium;">Having come from C++, I did not see the need for constraints, at
first. I knew it would make it easier for the compiler to give more
meaningful error messages (rather than the monstrosities of C++), but there
is a bit more to it than that.</span>
</p>
<p>
<span style="color: #3d85c6; font-size: large;">Improved Error Messages</span>
</p>
<p>
<span style="font-size: medium;">First, let's consider what the Min() function would look like without
constraints:</span>
</p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func Min[T](v1, v2 T) T { <span style="font-size: x-small;">// NOTE: invalid (missing constraint)</span></span><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> if v1 < v2 {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v1</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> }</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v2</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="font-size: medium;">Now if someone called this (hypothetical) generic function with bool arguments like this:</span></p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> Min(true, false) <span style="font-size: x-small;">// ERROR</span><br /></span></div>
<p>
<span style="font-size: medium;"><span>they'd get an error message about operator
<b><span style="color: #e69138;">< </span></b>not being defined for
<span style="color: #b45f06;">bool</span>, and you'd have to look at the
source code for <span style="color: #b45f06;">Min()</span> to understand
exactly what is happening. This may not look too hard but with more
complicated use of generics it becomes extremely difficult if not impossible
for the compiler to produce easily decipherable error messages.</span>
</span></p>
<p>
<span style="font-size: medium;">Now let's see how constraints help: because we are using less than
(operator<span style="color: #b45f06;"><b> <</b></span>) on the values of type <span style="color: #e69138;">T</span>, we need to
use the
<span style="color: #b45f06;">constraints.Ordered</span> constraint:</span>
</p>
<div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func Min[T constraints.Ordered](v1, v2 T) T { // OK</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> if v1 < v2 {</span></div><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> </span><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">return v1</span></div><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> </span><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> </span><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">return v2</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="font-size: medium;">Now if you try to call <span style="color: #b45f06;">Min()</span> with
<span style="color: #b45f06;">bool</span> parameters you get an error that
tells you that you can't - ie an error message like:
<i>bool does not satisfy constraints.Ordered</i>.</span></p>
<p>
<span style="font-size: medium;">On the other hand if you don't constrain the type parameter correctly,
eg:</span>
</p>
<div style="background-color: #e1e1e1;"><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func Min[T any](v1, v2 T) T {</span><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> if v1 < v2 { <span style="font-size: x-small;">// ERROR: cannot compare v1 < v2 (op < not defined for T)</span></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v1</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> }</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v2</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="font-size: medium;">you get an error since not all types support the less than
operation.</span></p>
<p>
<span style="font-size: medium;">Of course, you should ensure that you don't unnecessarily constrain a
type parameter. So if you used <span style="color: #b45f06;">constraints.Integer</span>
for the above <span style="color: #b45f06;">Min()</span> function's type parameters you'd be preventing
<span style="color: #b45f06;">Min()</span> being called for <span style="color: #b45f06;">float64 </span>or <span style="color: #b45f06;">string
</span> types.</span>
</p>
<p>
<span style="color: #3d85c6; font-size: large;">The Other Benefit of Constraints</span>
</p>
<p>
<span style="font-size: medium;">The other benefit of constraints, that I did not pick up on immediately, is
that they act as a <b><i>contract </i></b>between the creator and the user of the generic
function/type. Without a constraint the creator of the generic
function/type may update their code and inadvertently change the allowed
types. For example, if the creator of
<span style="color: #b45f06;">Min()</span> made this code "improvement"
(modifying our un-constrained<span style="color: #b45f06;"> Min() </span>example from above):</span>
</p>
<div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func Min[T](v1, v2 T) T { <span style="font-size: x-small;">// NOTE: currently invalid (missing constraint)</span></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> if v1 - v2 < 0 {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v1</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> }</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v2</span></div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">}</span></div>
<p><span style="font-size: medium;"><span>they may not realise they have made a change that will possibly break code
of some clients. Only when someone uses
</span><span style="color: #b45f06;">Min()</span><span> with string parameters would the
problem be detected.</span></span></p><div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> Min("abc", "xyz") <span style="font-size: x-small;">// ERROR: operator - not defined for string</span></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> Min(1, 2) <span style="font-size: x-small;">// still OK</span></span></div></div><p><span style="font-size: medium;">But using constraints, the creator will know right away if they have
violated the "contract", since not all types of <span style="color: #b45f06;">constraints.Orderered</span> allow
subtraction.</span></p>
<div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">func Min[T constraints.Ordered](v1, v2 T) T {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> if v1 - v2 < 0 { <span style="font-size: x-small;">// ERROR: invalid operation: (op - not defined for T)</span></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v1</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> }</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return v2</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div>
<p><span style="font-size: medium;">Without constraints the problem may not be found until some unsuspecting
user updates the package and finds that their code won't build.</span></p>
<p><b style="color: #3d85c6; font-size: x-large;">Creating Constraints</b></p>
<p><span style="font-size: medium;">So how do you use constraints when you create a generic function or type?
First, you need to decide on what capabilities are needed for a type
parameter. As we saw above the <span style="color: #b45f06;">Min()</span> function requires its
type parameters to support the less than operation which is specified with a
constraint of <span style="color: #b45f06;">constraints.Ordered</span>.</span></p>
<p>
<span style="font-size: medium;"><span>There are essentially three ways that you can constrain a type parameter,
by specifying:</span>
</span></p>
<p></p>
<ol style="text-align: left;">
<li>
<span style="font-size: medium;"><span>specific method signature(s) that the type must implement</span>
</span></li>
<li>
<span style="font-size: medium;"><span>explicit list of types (such as used in <span style="color: #b45f06;">contraints.Ordered</span>)</span>
</span></li>
<li>
<span style="font-size: medium;">built-in constraints (such as <span style="color: #b45f06;">comparable</span>) - determined by
the compiler</span>
</li>
</ol>
<p></p>
<p>
<span style="font-size: large;"><span style="color: #3d85c6;">1. Method Signature Constraints</span>
</span></p>
<p>
<span style="font-size: medium;"><span>Lets look at method signatures first as I think they are the reason for the
latest change to use <span style="color: #b45f06;">interface</span> instead of
<span style="color: #b45f06;">contract</span>. Currently in Go, a list of method signatures can be bundled
together for the purpose of defining an <span style="color: #b45f06;">interface</span> type. A similar
requirement for constraints is to restrict a type to only types that
implement certain method signature(s). Due to this similarity it was
decided constraints can just recycle the syntax used for <span style="color: #b45f06;">interface</span>.</span>
</span></p>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;"><span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">... it's important<br />to distinguish<br />the two different<br />uses of interface”</span></div>
<p>
<span style="font-size: medium;">For example, say we want a generic function called <span style="color: #b45f06;">Stringify()</span> that
requires its parameter to implement the <span style="color: #b45f06;">String()</span> method. This
constraint is specified using the following interface (which is already
available from the standard library<span style="color: #b45f06;"> fmt</span> package):</span></p>
<div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type Stringer interface {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> String() string</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"><br /></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">func Stringify[T Stringer](s T) string {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> return s.String()</span></div>
<div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div>
</div><p><span style="font-size: medium;">Note that it's important to distinguish the two very different uses of
<span style="color: #b45f06;">interface</span> that this change introduces:</span></p>
<p></p>
<ul style="text-align: left;">
<li><span style="font-size: medium;"><span>a type for variables of any type that implement certain method(s)</span></span></li>
<li><span style="font-size: medium;"><span>new use of creating a generic constraint for a type parameter</span>
</span></li>
</ul>
<p></p>
<p>
<span style="font-size: medium;"><span>I think of these as <b><i>run-time</i></b> and <b><i>compile-time</i></b> use of interfaces.</span>
</span></p>
<p>
<span style="font-size: medium;"><span>I have already seen questions in the
<a href="https://github.com/golang/go/issues" target="_blank"><span style="color: #2b00fe;">Go issue tracker</span></a>
where this double duty causes confusion, so you need to be clear on how the
new "compile-time" use of interfaces for generics differs from the original
use.</span>
</span></p>
<p>
<span style="font-size: medium;">There is also the further confusion that interfaces (since they are a type)
can also be generic and these generic interfaces can even be used a
constraints on other generic types. I'm not going to give an example as, to
be honest, I am not fully cognizant myself. BTW I believe that my earlier
proposal for constraints is simpler and less confusing (see <a href="http://devmethodologies.blogspot.com/2019/08/example-types-as-contracts.html" target="_blank"><span style="color: #2b00fe;">Example Types as Contracts</span></a>).</span></p>
<p><span style="color: #3d85c6; font-size: large;">2. List of Types</span></p>
<p>
<span style="font-size: medium;"><span>To allow the interface syntax to serve double duty as type parameter
constraints it has been extended to allow a list of types to be included in
an interface. For example, if a generic function only works for unsigned
integers then you could create a constraint like this:</span></span></p><div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">type UnsignedInteger interface {<br /> //type uint, uint8, uint16, uint32, uint64</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"><span> // Ed 2021: the above syntax is out of date, use this now:</span><br /></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> uint | uint8 | uint16 | uint32 | uint64</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"><br /></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">func MinValue[T UnsignedInteger]() T { <span style="font-size: x-small;">// min value for unsigned ints</span></span></div><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;"> return 0</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div><p><span style="font-size: medium;"><span>It's important to note that this interface syntax can only be used for a
constraint. An interface that includes a list of types cannot be used
for the original "run-time" duty of interfaces like declaring an interface variable.
(Ian Lance Taylor has a
</span><a href="https://github.com/golang/go/issues/41716" target="_blank"><span style="color: #2b00fe;">further proposal</span></a><span>
to allow this.)</span></span></p>
<p>
<span style="font-size: medium;"><span>You can, of course, combine a list of types plus method signatures in the
same interface. Here is a constraint that only allows unsigned
integers that have a <span style="color: #b45f06;">String()</span> method:</span></span></p><div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type Unsigned interface {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> uint | uint8 | uint16 | uint32 | uint64</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> String() string</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div><p><span style="font-size: medium;">Looking back at the definition of our <span style="color: #b45f06;">Min()</span> function you might now guess
where the <span style="color: #b45f06;">constraints.Ordered </span>constraint comes from. It's defined in
the constraints package, which undoubtedly will be added to the Go standard
library once the language supports generics. It is simply defined as a
list of types that support comparison/ordering operations (==, <, >=,
etc):</span></p><div style="background-color: #e1e1e1;"><div><span style="color: #b45f06; font-family: Courier New, Courier, monospace;">type Ordered interface {</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> //type int, int8, int16, int32, int64,</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> // uint, uint8, uint16, uint32, uint64, uintptr,</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> // float32, float64,</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> // string</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> // Ed 2021: the above syntax is out of date, use this now:<br /></span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> int | int8 | int16 | int32 | int64 |</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> uint | uint8 | uint16 | uint32 | uint64 |</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;"> float32 | float64 | string</span></div><div><span style="color: #b45f06; font-family: "Courier New", Courier, monospace;">}</span></div></div><p><span style="font-size: medium;">Most of the time you won't need to define your own constraints but use
those included in <b><i>constraints</i></b> package (or built in to the language). In
fact it's more robust to do so in case the language changes (for example
more types might be added to <span style="color: #b45f06;">constraints.Ordered</span> in
the future).</span></p>
<p>
<span style="color: #3d85c6; font-size: large;">3. Built-in Constraints</span>
</p>
<p>
<span style="font-size: medium;"><span>Finally, there are some constraints that can't be handled by a simple list of
types. The only one (apart from
<span style="color: #b45f06;">any</span>) that I am aware of is the
<span style="color: #b45f06;">comparable</span> constraint, which just
determines if two objects of a certain type can be compared for equality (ie
support == and != operations). This is not a simple rule - for example some
types of <span style="color: #b45f06;">struct</span> can be
compared but others can't.</span>
</span></p>
<p>
<span style="font-size: medium;"><span>I think I talked about the rules for <b><i>comparability</i></b> of types before, but
I'll explain it again in brief. Some basic types are not comparable,
for reasons we won't go into (except to
<span style="color: #b45f06;">nil</span>) - these are slices, maps and
funcs. Further, if you create an array of a non-comparable type, or a
struct that has one of these types as a field, or an interface that stores
one of these types then that type is also non-comparable (though in the case of interfaces this cannot be determined at compile time and will cause a run-time panic).</span></span></p>
<p>
<span style="font-size: medium;">Anyway, the simple rule is that if values of your generic type-parameter need to be compared for equality then you need to use the
<span style="color: #b45f06;">comparable</span> constraint.</span>
</p>
<p><b style="color: #3d85c6; font-size: xx-large;">Trying Go Generics</b></p>
<p>
<span style="font-size: medium;"><span>You can try Go generics using the latest syntax very easily using either
the <a href="https://go2goplay.golang.org/" target="_blank"><span style="color: #2b00fe;">go2go playground</span></a>. You can also build the dev branch of the Go
compiler source then use the included go2go tool - see
<a href="https://go.googlesource.com/go/+/refs/heads/dev.go2go/README.go2go.md" target="_blank"><span style="color: #2b00fe;">go2go README</span></a> for
instructions.</span>
</span></p>
<p><span style="font-size: medium;">The go2go tool translates your code quickly and the code runs
fast. There are a few little deficiencies that I have found such as
lack of support for external tests, build tags and <span style="color: #b45f06;">unsafe.Sizeof </span>but overall
it works very well.</span></p>
<p><b style="color: #3d85c6; font-size: xx-large;">Conclusion</b></p>
<p><span style="font-size: medium;">I can see some great packages being built with Go generics in the future. Especially important, I think, will be generic channels as this is something not offered in any other language and I think will greatly enhance the possibilities for concurrency.</span></p><p><span style="font-size: medium;">I've also written a completely new <a href="https://github.com/AndrewWPhillips/rangeset" target="_blank">generic set container called rangeset</a> that implements sets (constrained to integers) using ranges. This has some very interesting performance capabilities for some types of sets and also allows inversion and universal sets (something not supported by the <a href="https://go.googlesource.com/go/+/refs/heads/dev.go2go/src/cmd/go2go/testdata/go2path/src/sets/" target="_blank">example go2go set package</a>). I'll talk about this in a post soon.</span></p><p><span style="font-size: medium;">I was also going to say a few more things that I haven't had time for. I'll try to flesh out my notes and publish another post in the next few weeks. This will include:</span></p><ul style="text-align: left;"><li><span style="font-size: medium;">some benchmarks of generic code</span></li><li><span style="font-size: medium;">+ compilation times of generic code using the go2go tool</span></li><li><span style="font-size: medium;">my experiments with generic channels</span></li></ul><p></p><p><br /></p>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-8060423836820861932019-10-05T14:43:00.001+10:002019-10-05T14:43:06.269+10:00Overview<span style="color: #666666;">I have reorganized this Overview since all my posts in the past few years have been about <b>Go</b> which is now near the top. My previous pet subject (Agile) is now towards the bottom.</span><br />
<br />
<span style="color: #0b5394;"><span style="font-size: x-large;">Coding</span></span><br />
<br />
<span style="color: #3d85c6; font-size: large;">Go Coding</span><br />
<br />
<a href="https://devmethodologies.blogspot.com.au/2017/08/the-essence-of-go.html"><span style="color: blue;">The Essence of Go</span></a> - reading about Go you don't realize how nice it is to use<br />
<a href="https://devmethodologies.blogspot.com.au/2017/10/improving-go-error-handling.html"><span style="color: blue;">Improving Go Error Handling</span></a> - how to fix one part of Go that is not so nice<br />
<a href="https://devmethodologies.blogspot.com.au/2017/11/active-object.html"><span style="color: blue;">Active Object</span></a> - a powerful concurrency pattern that Go makes easy<br />
<a href="http://devmethodologies.blogspot.com/2019/02/type-safe-channels-in-go.html"><span style="color: blue;">Type Safe Channels</span></a> - avoiding bugs when a channel must accept multiple types<br />
<a href="http://devmethodologies.blogspot.com/2018/10/go-puzzles-not-interview-questions.html"><span style="color: blue;">Go Puzzles</span></a> - 33 coding puzzles to test your knowledge of Go<br /><a href="http://devmethodologies.blogspot.com/2018/11/go-puzzle-solutions.html"><span style="color: blue;">Puzzle Solutions</span></a> - don't look at the answers till you've tried the puzzles<br /><a href="http://devmethodologies.blogspot.com/2018/10/go-error-handling-using-closures.html"><span style="color: blue;">Go Error Handling Using Closures</span></a> - response to <a href="https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md">Error Handling Draft Design</a><br />
<a href="http://devmethodologies.blogspot.com/2019/08/example-types-as-contracts.html"><span style="color: blue;">Example Types as Contracts</span></a> - response to <a href="https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md">2019 Generics Draft Design</a><br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">C Coding</span></span><br />
<br />
<span style="color: #45818e;"><a href="http://devmethodologies.blogspot.com.au/2013/07/best-practice-in-c-for-modules.html" target="_blank">Best Practice in C for Modules</a> </span>- high-coupling and other things to avoid<br />
<a href="http://devmethodologies.blogspot.com.au/2012/05/defensive-programming.html" target="_blank">Defensive Programming</a> - how it works and how it can hide bugs<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/shotgun-initialization.html" target="_blank">Shotgun Initialization</a> - a defensive programming practice to avoid<br />
<a href="http://devmethodologies.blogspot.com.au/2013/04/alignment-and-pragma-pack.html" target="_blank">Alignment and #pragma pack</a> - make structs "alignment agnostic" to avoid surprises<br />
<span style="color: #45818e;"><a href="http://devmethodologies.blogspot.com.au/2012/11/verifiability.html" target="_blank"><span style="color: blue;">Making Code Testable</span></a><span style="color: #45818e;"> </span></span>- coding for testability improves correctness, reliability, etc<br />
<a href="http://www.codeproject.com/Articles/357065/Ten-Fallacies-of-Good-C-Code" target="_blank">Ten Fallacies of Good C Code</a> [CodeProject] - 10 more things to avoid<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">C++ Coding</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/05/stls-dark-secret.html" target="_blank">STL's Dark Secret</a> - vectors are slower than they should be<br />
<a href="http://devmethodologies.blogspot.com.au/2013/08/iterators-through-looking-glass.html" target="_blank">Iterators Through the Looking Glass</a> - subtleties of the STL reverse iterators<br />
<a href="http://devmethodologies.blogspot.com.au/2013/06/c11-and-lambda-functions.html" target="_blank">C++11 and Lambda Functions</a> - lambda functions make STL so much better<br />
<a href="http://devmethodologies.blogspot.com.au/2013/07/nesting-functions-using-lambdas_13.html" target="_blank">Nested Functions using Lambdas</a> - you can finally have nested functions in C++11<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">C# Coding</span></span><br />
<br />
<a href="https://devmethodologies.blogspot.com.au/2017/05/why-i-like-c.html"><span style="color: blue;">Why I Like C#</span></a> - lots of nice things (and it's not really that much slower than C)<br />
<a href="http://www.codeproject.com/Articles/7776/Arithmetic-Overflow-Checking-using-checked-uncheck" target="_blank">Overflow Checking using checked/unchecked</a> [CP] - C# has some cool features<br />
<a href="http://devmethodologies.blogspot.com.au/2013/07/nesting-functions-using-lambdas_13.html" target="_blank">Nested Functions using Lambdas</a> - includes an example of using C# lambdas<br />
<div>
<br /></div>
<span style="color: #3d85c6;"><span style="font-size: large;">Maintainability</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/04/long-identifiers-make-code-unreadable.html" target="_blank">Long Identifiers make Code Unreadable</a> - don't try to put too much info. into a name<br />
<a href="http://devmethodologies.blogspot.com.au/2012/06/self-describing-code.html" target="_blank">Self Describing Code</a> - why it's a bad idea and why you should comment your code<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Other</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2011/11/zero.html" target="_blank">Zero</a> - bugs are less likely if you don't treat zero as a special case<br />
<a href="http://devmethodologies.blogspot.com.au/2012/12/asymmetric-bounds-and-zero-based.html" target="_blank">Asymmetric Bounds</a> - in code and GUI design this is an important way to avoid bugs<br />
<a href="http://devmethodologies.blogspot.com.au/2013/10/book-review-clean-code.html" target="_blank">Book Review: Clean Code</a> - a great book on creating the best code<br />
<a href="http://devmethodologies.blogspot.com.au/2012/05/phillips-scale-of-code-quality.html" target="_blank">The Phillips Scale of Code Quality</a> - how good is your code?<br />
<a href="http://devmethodologies.blogspot.com.au/2016/11/version-control-personal-experiences.html">Version Control - Personal Experiences</a> - hands on version control<br />
<br />
<span style="color: #0b5394;"><span style="font-size: x-large;">Software Design</span></span><br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Design Principles</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2011/10/handling-software-design-complexity.html" target="_blank">Handling Software Design Complexity</a> - what software design all boils down to<br />
<a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE</a> - an obvious thing we often forget<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/importance-of-developer-quality.html" target="_blank">Developer Quality Attributes</a> - or why fixing bugs is <i><b>not</b></i> important<br />
<span id="goog_1873098402"></span><span id="goog_1873098403"></span><a href="http://devmethodologies.blogspot.com.au/2012/11/verifiability.html" target="_blank"><span style="color: blue;">Verifiability</span></a> - software is useless unless you can verify its correctness<br />
<a href="http://devmethodologies.blogspot.com.au/2012/03/code-degradation.html" target="_blank">Why Good Programs Go Bad</a> - risk avoidance causes software to "rust"<br />
Book Review: 97 Things Every Architect Should Know<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Design Practices</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/08/fundamentals-of-software-design.html" target="_blank">Fundamentals of Software Design</a> - 8 ways to create a good design<br />
<a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">Agile Design</a> - how emergent design almost always works better than BDUF<br />
<a href="http://devmethodologies.blogspot.com.au/2012/06/inversion-of-control.html" target="_blank">Inversion of Control</a> - IOC is a technique for better decoupling using DIRE<br />
<a href="http://devmethodologies.blogspot.com.au/2012/07/dependency-injection.html" target="_blank">Dependency Injection</a> - an example of IOC<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Anti-Patterns</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/12/the-gas-factory-anti-pattern.html" target="_blank">Gas Factory Anti-Pattern</a> - a mistake even (or especially) good designers make<br />
<span style="color: blue;"><a href="http://devmethodologies.blogspot.com.au/2012/11/reusability-futility.html" target="_blank"><span style="color: #45818e;">Reusability Futility</span></a> </span>- "Simplicity before Generality, Use before Reuse"<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/shotgun-initialization.html" target="_blank">Shotgun Initialization</a> - an example of the dangers of defensive programming<br />
<a href="http://devmethodologies.blogspot.com.au/2012/10/the-layer-anti-pattern.html" target="_blank">Layer Anti-Pattern</a> - the problems of a common, obvious approach<br />
<span style="color: #45818e;"><a href="https://devmethodologies.blogspot.com.au/2013/02/ignore-divide-by-zero.html">Ignore Divide By Zero</a></span> - commonly taught practices can be wrong<br />
<a href="http://devmethodologies.blogspot.com.au/2012/05/defensive-programming.html" target="_blank">Defensive Programming</a> - it can hide bugs<br />
<br />
<span style="color: #0b5394;"><span style="font-size: x-large;">Agile</span></span><br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Principles</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2014/09/agiles-fifth-element.html" target="_blank">Agile's Fifth Element</a> - favor simple design over re-usability and generality<br />
<a href="http://devmethodologies.blogspot.com.au/2014/04/jit.html" target="_blank">JIT (Just In Time)</a> - an example of DIRE that is core to much of Agile<br />
<a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE (Don't Isolate Related Entities)</a> - <i>how</i> you divide and conquer is the key<br />
<a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">Agile Design</a> - evolving software one small step at a time<br />
<a href="http://devmethodologies.blogspot.com.au/2012/11/reusability-futility.html" target="_blank"><span style="color: blue;">Agile and Code Reuse</span></a> - all about YAGNI (you ain't gonna need it)<br />
<a href="http://devmethodologies.blogspot.com.au/2012/07/sqa-and-agile-methodologies.html" target="_blank">Software Quality Assurance & Agile</a> - how Agile evolved from, but is different to, SQA<br />
<a href="http://devmethodologies.blogspot.com.au/2015/01/lean-is-not-agile.html" target="_blank"><span style="color: blue;">Lean is not Agile</span></a> - applying "eliminate waste" to software design leads to BDUF<br />
<a href="http://www.codeproject.com/Articles/124732/Software-Development-Methodologies" target="_blank">Software Development Methodologies</a> [CP] - Agile and other methodologies by analogy<br />
<a href="https://devmethodologies.blogspot.com.au/2015/02/scrum-communism.html"><span style="color: blue;">Scrum is like Communism?</span></a> - maybe it is, but that does not mean it is doomed to failure!<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Team</span></span><br />
<br />
<a href="https://devmethodologies.blogspot.com.au/2014/12/agile-roles.html"><span style="color: blue;">Agile Roles</span></a> - when Agile is done properly all roles <i>do</i> change (some even disappear)<br />
<a href="http://devmethodologies.blogspot.com.au/2015/03/scrum-team-size.html" target="_blank">Scrum Team Size</a> - teams should be small to avoid social loafing and other phenomena<br />
<a href="http://devmethodologies.blogspot.com.au/2015/04/scrum-team-composition.html" target="_blank">Scrum Team Composition</a> - "feature" teams are the key<br />
<a href="http://devmethodologies.blogspot.com.au/2015/04/team-collaboration.html" target="_blank">Collaboration</a> - traditional development discourages collaboration + why Scrum works<br />
<a href="https://devmethodologies.blogspot.com.au/2014/12/production-line-mentality-and-silo.html"><span style="color: blue;">Production Line Mentality</span></a> - the reason teams don't collaborate<br />
<br />
<span style="color: #3d85c6;"></span><span style="color: #3d85c6;"><span style="font-size: large;">Making Agile Work</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/10/scrum-standup.html" target="_blank"><span style="color: blue;">Scrum Standup</span></a> - it's more about visibility than communication<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/importance-of-developer-quality.html" target="_blank">Developer Quality Attributes</a> - what benefits developers eventually helps users<br />
<a href="http://devmethodologies.blogspot.com.au/2016/09/agile-version-control.html" target="_blank">Agile Version Control</a> - Agile requires the right version control practices & software (Git)<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/scrum-problems.html" target="_blank">Scrum Problems</a> - management "buy-in" & other things that help Scrum work properly<br />
<a href="http://devmethodologies.blogspot.com.au/2013/01/why-scrum-fails.html" target="_blank">Why Scrum Fails</a> - intransigence, non-collaboration, etc<br />
<a href="http://devmethodologies.blogspot.com.au/2015/09/written-vs-verbal.html" target="_blank">Written vs Verbal</a> - when, who, why, and how of Agile documentation<br />
<a href="http://devmethodologies.blogspot.com.au/2012/01/jit.html" target="_blank">JIT Testing</a> - testing as you go (continuous testing) is an example of JIT (Just In Time)<br />
<a href="https://devmethodologies.blogspot.com.au/2015/01/vendor-mentality.html"><span style="color: blue;">Vendor Mentality</span></a> - another "mentality" you need to overcome<br />
<a href="https://devmethodologies.blogspot.com.au/2013/09/customer-management.html"><span style="color: blue;">Customer Management</span></a> - the customer is not always right<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Unit Tests</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/10/change.html" target="_blank">Change</a> - how Unit Tests help you to embrace change<br />
<a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-whats-so-good-about-them.html" target="_blank">What's so great about Unit Tests</a> - Unit Tests are not about finding bugs<br />
<a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-white-box-testing.html" target="_blank">White Box Testing</a> - the best Unit Tests use "good" white box testing<br />
<a href="http://devmethodologies.blogspot.com.au/2013/12/unit-tests-personal-experiences.html" target="_blank">Personal Experiences with Unit Testing</a> - it took me 20 years to truly appreciate them<br />
<a href="http://devmethodologies.blogspot.com.au/2014/01/unit-tests-challenges.html" target="_blank">Challenges</a> - why getting started with Unit Tests seems, but is not, insurmountable<br />
<a href="http://devmethodologies.blogspot.com.au/2014/01/unit-tests-best-practice.html" target="_blank">Unit Tests Best Practice</a> - a few things to avoid<br />
<a href="http://devmethodologies.blogspot.com.au/2014/03/arguments-against-unit-tests.html" target="_blank">Arguments Against Unit Tests</a> - common arguments and why most are invalid<br />
<a href="http://devmethodologies.blogspot.com.au/2014/03/unit-tests-summary.html" target="_blank">Summary</a> - Unit Tests concisely summarized<br />
<br />
<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com4tag:blogger.com,1999:blog-7237530825191390698.post-15595280609565173182019-08-24T13:30:00.004+10:002019-10-05T12:06:47.545+10:00Go: Example Types as Contracts<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<h2 style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;">
<span style="font-weight: normal;"><span style="color: #3d85c6; font-size: large;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Summary</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></span></h2>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">The sticking point with adding <i><b>parametric polymorphism</b></i> to Go is how to specify which type(s) are allowed to be used as type parameters. Contracts are a good way. A simpler way is to use <b><i>example types</i></b> as detailed below. I believe this would make creating generic functions/datatypes simpler and easier to fathom but with the same benefits as contracts.</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span><br />
<span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><br /></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<h2 style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;">
<span style="font-weight: normal;"><span style="color: #3d85c6; font-size: large;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Introduction</span></span></span></h2>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">I think the <b>2019 Contracts Draft Design</b> is great. I would be more than happy if it were implemented, but there are some who think the use of contracts could be simplified or avoided and maybe they are right.</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">[Personally, I have been using C++ templates for more than 20 years and am happy with having no way to specify constraints on type parameters. (That is C++ (before Concepts) leaves it to the compiler to at some point detect if a specific type does not provide a capability required by a type parameter.) But I concede that even the best C++ compilers produce tedious (but ultimately decipherable) error messages and this is just not acceptable for Go where getting code to build is much </span><span class="SpellingError SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">much</span><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> easier than C++ and other languages. Moreover, as pointed out in the Draft Design, a mechanism such as contracts can make code more resilient by preventing a change to a generic function/type having an unintended change to the type parameter requirements and consequently breaking distant code.]</span></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
BTW From now on I will use the term <b><i>generic</i></b> as a shorthand for <b><i>parametric polymorphism</i></b>.</div>
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Go is renowned for making things simple, so my approach was to look at how I (and others) use "generics" in other languages then look at how to make that process as simple as possible. In my experience, generic functions and datatypes are generally created in a vanilla (non-generic) version first, then converted. In other words rather than starting with a type parameter off the bat, you start with a simple "example" type first, get it working, then convert the example type to a type parameter.</span></div>
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><br /></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; color: #3d85c6; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: large; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Using Example Types</span></div>
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">My proposal is to stick with the example type in Go and just indicate that it can be replaced with other types, as long as they have the same capabilities. Of course, it's not that simple, but I will address the issues shortly.</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">First, a simple example will help. Let's start with the most obvious generics example – a function to find the minimum value. Here is the Go code using </span><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span style="color: #b45f06;"><b>int</b></span></span><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func Min(first int, rest ...int) (retval int) {<br />
retval = first<br />
for _, v := range rest {<br />
if v < retval {<br />
retval = v<br />
}<br />
}<br />
return<br />
}</div>
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">To convert we make one small change to indicate that <b><span style="color: #b45f06;">int</span></b> is a type parameter. Thence anywhere<b><span style="color: #b45f06;"> int</span></b> is used it is replaced with the type of the type parameter.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-text-stroke-width: 0px; background-color: transparent; color: black; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; overflow-wrap: break-word; padding: 0px; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: 2; word-spacing: 0px;" xml:lang="EN-US">
</div>
<br />
<div style="-webkit-text-stroke-width: 0px; background-color: #e1e1e1; font-family: "courier new", courier, monospace; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div style="margin: 0px;">
<span style="color: #b45f06;">func Min</span><b><span style="color: #cc0000;">(type int)</span></b><span style="color: #b45f06;">(first int, rest ...int) (retval int) {</span><br />
<span style="color: #b45f06;"> retval = first</span><br />
<span style="color: #b45f06;"> for _, v := range rest {</span></div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
if v < retval {</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
retval = v</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
}</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
}</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
return </div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
}</div>
</div>
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Now you can use <b><span style="color: #b45f06;">Min()</span></b> with any integer type like <b><span style="color: #b45f06;">rune</span></b> or <b><span style="color: #b45f06;">uint64</span></b>.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">The first problem you will probably have already seen is that you may need to use an actual <b><span style="color: #b45f06;">int</span></b> in the code and not have it take on the generic type. To do this (and make the code more resilient to changes) you can define a new type.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br />
<div style="background-color: #e1e1e1; font-family: "courier new", courier, monospace;">
<b><span style="color: #cc0000;">type minT int</span></b><br />
<span style="color: #b45f06;">func Min(type </span><b><span style="color: #cc0000;">minT</span></b><span style="color: #b45f06;">)(first </span><b><span style="color: #cc0000;">minT</span></b><span style="color: #b45f06;">, rest ...</span><b><span style="color: #cc0000;">minT</span></b><span style="color: #b45f06;">) (retval </span><b><span style="color: #cc0000;">minT</span></b><span style="color: #b45f06;">) {</span><br />
<span style="color: #b45f06;"> retval = first</span><br />
<span style="color: #b45f06;"> for _, v := range rest {</span><br />
<div style="color: #b45f06;">
if v < retval {</div>
<div style="color: #b45f06;">
retval = v</div>
<div style="color: #b45f06;">
}</div>
<div style="color: #b45f06;">
}</div>
<div style="color: #b45f06;">
return </div>
<div style="color: #b45f06;">
}</div>
</div>
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Note that by convention you might be inclined to use a name for the type of <b><span style="color: #b45f06;">T</span></b> - but something like <b><span style="color: #b45f06;">minT </span></b>is safer as it is not exported and is less likely to conflict with other uses of generics in the package.</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span><br />
<span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><br /></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<h2>
<span style="color: #3d85c6; font-size: large;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span style="font-weight: normal;">New </span>Orderable<span style="font-weight: normal;"> Type</span></span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-weight: normal; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></h2>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Now the only reason we use <b><span style="color: #b45f06;">int </span></b>as the "example type" in the generic <b><span style="color: #b45f06;">Min()</span></b> function is so we can test the order of values, using the less than operator (<b><span style="color: #b45f06;"><</span></b>) in this case. But strings and floating point types also support less than. We should be able to get a minimum value for those too. That is why I propose adding a new (non-instantiable) type to the language called <b><i>orderable</i></b>. Now <b style="font-size: 14.6667px;"><span style="color: #b45f06;">Min() </span></b>can work with strings too.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-text-stroke-width: 0px; background-color: white; clear: both; color: black; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="-webkit-text-stroke-width: 0px; background-color: #e1e1e1; font-family: "courier new", courier, monospace; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div style="margin: 0px;">
<span style="color: #b45f06;"><span style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">func Min(type </span><b style="color: black;"><span style="color: #cc0000;">orderable)</span></b><span style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">(first </span><b style="color: black;"><span style="color: #cc0000;">orderable</span></b><span style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">, rest ...</span><b style="color: black;"><span style="color: #cc0000;">orderable</span></b><span style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">) (retval </span><b style="color: black;"><span style="color: #cc0000;">orderable</span></b><span style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">) {</span></span><br />
<span style="color: #b45f06;"> retval = first</span><br />
<span style="color: #b45f06;"> for _, v := range rest {</span></div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
if v < retval {</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
retval = v</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
}</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
}</div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
return </div>
<div style="color: #b45f06; font-weight: 400; margin: 0px;">
}</div>
</div>
<div style="margin: 0px;">
<br /></div>
</div>
</div>
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Note that you can't declare a variable of type <b><span style="color: #b45f06;">orderable </span></b>except in a generic function or type that uses an <b><span style="color: #b45f06;">orderable </span></b>type parameter.</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">The compiler knows what types support ordering so this approach will adapt (unlike the <b>2019 Contracts Draft Desing</b> I believe) to future language changes - for example if an <b><span style="color: #b45f06;">int128 </span></b>type is added or if ordering (<b><span style="color: #b45f06;"><</span></b>, <span style="color: #b45f06;"><b>>=</b></span>, etc) is later extended to other types such as some subset of <b><span style="color: #b45f06;">struct</span></b>s.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">We might also want to hide the public name of this new type in the <b><span style="color: #b45f06;">generics </span></b>package, to avoid polluting the global namespace and possibly introducing conflicts with existing code. In other words the public type would be </span><span class="SpellingError SCXO247178529 BCX0" style="background-color: inherit; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;"><b>generics.Orderable</b></span><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> to hide the actual type (possibly with a name like <b><span style="color: #b45f06;">__orderable</span></b>).</span></span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span><br />
<span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><br /></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; color: #3d85c6; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: large; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Required Methods</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; color: #3d85c6; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: large; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Another important requirement for a type parameter is that it implements particular method(s). Here we demonstrate the common example of a function to convert a slice to a slice of strings. We need to ensure that the function is only called using a slice of a type that implements the <b><span style="color: #b45f06;">String()</span></b> method.</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;">type stringer struct {} </span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (stringer) String() string { return "" } </span><br />
<br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;">func Stringify(type stringer)(s []stringer) (retval []string) { </span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> for _, v := range s { </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> retval = append(retval, v.String()) </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> return </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">}</span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
</div>
</div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">Here stringer is the "example type" for the generic </span><span class="SpellingError SCXO247178529 BCX0" style="background-color: inherit; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;"><b>Stringify</b></span><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><b><span style="color: #b45f06;">()</span></b> function. One ugliness is that we have to implement a dummy <b><span style="color: #b45f06;">String()</span></b> method on the stringer type, but it doesn't really do much and the compiler would not need to generate any code for this function since it is never called.</span></span><br />
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><br /></span></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; font-size: medium; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<h2>
<span style="color: #3d85c6; font-size: large;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span style="font-weight: normal;">New </span>Any<span style="font-weight: normal;"> Type</span></span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-weight: normal; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></h2>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
</div>
</div>
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The above <b><span style="color: #b45f06;">stringer</span></b> type is based on an empty <b><span style="color: #b45f06;">struct </span></b>on the assumption that this can represent any type in Go. However, now that I think about it, this may preclude using </span><span class="SpellingError SCXO247178529 BCX0" style="background-color: inherit; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;"><b>Stringify</b></span><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><b><span style="color: #b45f06;">()</span></b> with a slice of some types. Maybe we also need to add a type to the language that can stand in for any type.</span></span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span><br />
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;"><span style="color: #b45f06;">type stringer </span><b><span style="color: #cc0000;">generics.Any</span></b><span style="color: #b45f06;"> </span></span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (stringer) String() (retval string) { }</span></div>
</div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; font-size: medium; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br />
<h2>
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; color: #3d85c6; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: large; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span style="font-weight: normal;">New </span>Comparable<span style="font-weight: normal;"> Type</span></span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; color: #3d85c6; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: large; font-weight: normal; line-height: 18px; margin: 0px; padding: 0px;"> </span></h2>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
</div>
</div>
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">Comparing types for equality is a little complicated in Go. Even the <b>2019 Contracts Draft Design</b> proposes a special predefined contract called "comparable" (which, I assume, is intended to be handled specially by the compiler). Similarly, in my proposal we have a new Go type called </span><span class="SpellingError SCXO247178529 BCX0" style="background-color: inherit; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;"><b>generics.Comparable</b></span><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> that includes all types that can be compared. (A cursory explanation is that slice, map, function types are non-comparable plus any array/struct/interface types that contain such non-comparable type(s).)</span></span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span><br />
<span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><br /></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Here is an example to demonstrate using the example from the </span><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><b>2019 Contracts Draft Design</b></span><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">:</span></div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<br /></div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type indexT generics.Comparable </span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;"><br /></span></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;">func Index(type indexT)(s []indexT, x indexT) int { </span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> for i, v := range s { </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> if v == x { </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> return i </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> } </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> } </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> return -1 </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">}</span></div>
</div>
</div>
</div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br />
<h2>
<span style="color: #3d85c6; font-size: large; font-weight: normal;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Types using Type Parameters</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></h2>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt;">I have <i>unintentionally </i>concentrated on generic functions above. Just for completeness I present a generic type as well – the ubiquitous pair.</span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"></span></span></div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-text-stroke-width: 0px; background-color: white; clear: both; color: black; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; font-size: medium; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
</div>
</div>
</div>
</div>
<br />
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type pairT1 generics.Any </span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type pairT2 generics.Any </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;"><br /></span></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;">type pair(type pairT1, pairT2) struct { </span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> first pairT1</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> second pairT2</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">}</span></div>
</div>
</div>
</div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<br /></div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 14.6667px;">This also demonstrates how to have more than one type parameter using the same example type. That is, <b><span style="color: #b45f06;">T1 </span></b>and <b><span style="color: #b45f06;">T2</span></b> use the same example type but can be instantiated with different actual types.</span><br />
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span style="color: #3d85c6; font-size: large;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Mutually Referencing Type Parameters</span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Of course, a function or type can have multiple type parameters, which can refer to each other. Again using an example from the<b> 2019 Draft Design</b></span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;">.</span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<br /></div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"></span></div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-text-stroke-width: 0px; background-color: white; clear: both; color: black; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; font-size: medium; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
</div>
</div>
</div>
</div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type node generics.Any</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (node) Edges() (edges []edge) { return } </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;"><br /></span></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;">type edge generics.Any </span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (edge) Nodes() (from, to node) { return } </span><br />
<br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><span style="font-size: 12px;">type Graph(type node, edge) struct { ... } </span></span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func New(type node, edge)(nodes []node) *Graph(node, edge) { ... } </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (g *Graph(node, edge)) ShortestPath(from, to node) []edge { ... } </span><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
</div>
</div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<h2>
<span style="color: #3d85c6; font-size: large; font-weight: normal;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Further Constraints</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></h2>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><span class="NormalTextRun SCXO247178529 BCX0" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">In my proposal certain types when used as a type parameter can stand in for any type that has the same capabilities. So int can stand in for all integer types. However, we may need further restrictions on allowed types for a type parameter such as only integers of at least 16 bits. In this case</span></span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> perhaps <b><span style="color: #b45f06;">int16</span></b> could mean any integer of 16 bits or more and <b><span style="color: #b45f06;">uint</span></b> could mean any unsigned integer, etc.</span><br />
<span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><br /></span>
<span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;">If this does not work well perhaps allow a new generic type to be defined from a set of existing types. This is similar to specifying a list of types in a contract in the <b>2019 Contracts Draft Design</b>.</span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br />
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-text-stroke-width: 0px; background-color: white; clear: both; color: black; cursor: text; direction: ltr; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; font-family: "Times New Roman"; font-size: medium; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">package generics</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"><br />type UInt16 {</span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">uint16, uint32, uint64}</span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"> // maybe uint128 later</span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"><br />type SInt16 </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">{int16, int32, int64}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;"><strike>type Int16 {int16, int32, int64, uint16, uint32, uint64}</strike></span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
</div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type Int16 {UInt16, SInt16}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br />
<h2>
<span style="color: #3d85c6; font-size: large; font-weight: normal;"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Embedding</span></span></h2>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">As in the <b>2019 Draft Design</b> example types can "embed" other types using the existing type embedding mechanism.</span></div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<br /></div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type printStringer struct{stringer} // embed stringer type from above</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (printStringer) Print() {}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"> </span><span class="EOP SCXO247178529 BCX0" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Alternatively you can just extend the existing type by adding a method.</span><br />
<br />
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-text-stroke-width: 0px; background-color: white; clear: both; color: black; cursor: text; direction: ltr; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; orphans: 2; overflow: visible; padding: 0px; position: relative; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div style="background-color: #e1e1e1;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">type printStringer stringer</span></div>
<div style="margin: 0px;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; font-size: 12px;">func (printStringer) Print() {}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px; margin: 0px;">
<br /></div>
</div>
</div>
<span style="background-color: transparent; color: #3d85c6; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: large;">Conclusion</span><br />
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><br />I actually wrote a draft of this proposal late last year after hearing Rob Pike's talk at the Sydney Go Meetup (October 2018?) about the 2018 <b>Draft Designs for Go 2</b>. Unfortunately, I never found the time to complete it, and was hoping that someone else would put forward a similar proposal. (The most similar proposal I have seen is Matt Sherman's [</span><a class="Hyperlink SCXO247178529 BCX0" href="https://clipperhouse.com/go-generics-typeclasses/" rel="noreferrer" style="background-color: transparent; margin: 0px; padding: 0px;" target="_blank"><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">https://clipperhouse.com/go-generics-typeclasses/</span></a><span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">].)</span><span class="EOP SCXO247178529 BCX0" style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU">Now that I have reviewed and polished this proposal I think it's rather similar to the <b>2019 Contracts Draft Design</b> but replaces the contracts with something more familiar and easier to grasp. The new contracts syntax is an improvement on the <b>2018 Contracts Draft Design</b> but is still confusing - a contract with methods looks much like an interface but must also include the receiver type for each method which looks out of place.</span></div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO247178529 BCX0" data-contrast="auto" lang="EN-AU" style="font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-AU"><br /></span></div>
<span style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 14.6667px;">This proposal makes it easy to write functions and datatypes in a non-generic version and convert them to generic ones.</span><span style="background-color: transparent; font-family: "calibri" , "calibri_msfontservice" , sans-serif; font-size: 11pt;"> Please post a comment below if I have missed something.</span></div>
</div>
<div class="OutlineElement Ltr BCX0 SCXO247178529" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO247178529 BCX0" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-11213449301278122242019-02-24T10:48:00.001+11:002019-03-07T09:58:49.283+11:00Type Safe Channels in GoI've recently been working on a backend system in Go. The design is highly parallelised with many small go-routines each handling a set of messages delivered to a channel, thence processing and possibly sending on results to the next channel(s) in the process (or to frontend via websocket). One of the first things I realized is that, due to the complexity of the system, it is easy to mistakenly write code that sends a specific message type to the wrong channel.<br />
<br />
To this end I developed a method of making the channels type-safe which I have not seen discussed before. This saved a lot of time building and debugging compared to other solutions (discussed below).<br />
<br />
There were a few hurdles with this approach. And another approach with the same type-safety is to select from multiple input channels each with their own specific type of message but the approach was the best in the circumstances.<br />
<br />
In this and subsequent posts I will explorer some of the hurdles I encountered, and the trade-offs between various solutions. To demonstrate the ideas I will create a demo using the example of a currency exchange server. This example is similar, though simpler, to the above-mentioned backend project which I cannot discuss here due to confidentiality (though I can say that it had nothing to do with currencies :).<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Type Safe Channels</b></span><br />
<br />
As I mentioned, the first hurdle was ensuring that the right messages are sent to the correct type of channel. In my backend project there were seven different channel types each of which could receive one or more different message types. (One channel type had more than 20 message types.)<br />
<br />
<span style="color: #3d85c6;"><b>Channels of Anything</b></span><br />
<br />
A simple approach would have been to allow the channels to receive any type of value by using the empty interface type.<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
var ch chan interface{}</div>
<br />
Then, in the go-routine for the channel, I would detect an unexpected message type like this:<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
for message := range ch {<br />
switch m := message.(type) {<br />
case ExpectedType:<br />
...<br />
default:<br />
panic("Unexpected message type for channel ch")<br />
}<br />
}</div>
<br />
Of course, this means that bugs aren't caught until run-time. In the worst case they are found by some unsuspecting user, because the particular circumstance of their occurrence was not covered by your tests. I was not happy at all with this approach and if you think it's a good idea I recommend you go back to Javascript or Python.<br />
<br />
<span style="color: #3d85c6;"><b>Multiple Channels</b></span><br />
<br />
A safer approach that I have seen elsewhere is to allow each go-routine to select from multiple channels with each channel having a different type.<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
var chInt chan int</div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> var chExpected chan ExpectedType</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> for {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> select {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> m := <-chExpected:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // handle ExpectedType message</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> m := <-chInt:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // handle int message</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<br />
<br />
This ensures, at compile time, that only messages of the correct type are sent since only channels of the correct type are connected.<br />
<br />
However, this solution is a bit cumbersome to maintain - eg when adding new message types. It is also wasteful of memory. For example, my backend could have more than 100,000 go-routines of a certain type each of which would require more than 20 (buffered) channels. This would require several GBytes of memory more than a solution which only had one channel per go-routine.<br />
<br />
I needed a way to restrict, at compile time, a single channel to receive a limited set of message types.<br />
<br />
<b><span style="color: #3d85c6;">Inheritance?</span></b><br />
<br />
In a more "OO" language I would just create a "base" class for each type of go-routine and all message types for that go-routine would inherit from this base class. In Go, if you could do this, it would look something like:<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
// WARNING this is not real Go code</div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> type (</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> baseObj1 struct{}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> obj1Mess1: baseObj1 struct{ /* fields for the message */ }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> obj1Mess2: baseObj1 struct{ /* fields for the message */ }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> baseObj2 struct{}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> obj2Mess1: baseObj2 struct{ /* fields for the message */ }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> )</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> var chType1 chan baseObj1 // only obj1Mess1, obj1Mess2</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> var chType2 chan baseObj2 // obj2Mess1 but not obj1Mess1, etc</span></div>
<br />
You can't do this in Go. But, in a way, Go does support "inheritance" - using interfaces. (In fact, I have found that Go and interfaces are sufficient to implement any useful design pattern.)<br />
<br />
And one problem with the above is that some message types are destined for more than one object. So some message types must be derived from more than one base class. This is not possible in languages, like Java and C#, that do not support multiple inheritance. However, these languages do allow you to "inherit" from more than one interface - which leads to something similar to what I came up with for Go...<br />
<br />
<span style="color: #3d85c6;"><b>Interfaces</b></span><br />
<br />
It's pretty clear that the best solution was to use channels of different interface types. I searched on the Internet for Go examples that used this technique but found none. Hence I am writing this post to describe the solution I came up with.<br />
<br />
In detail: I used one input channel per go-routine which could receive several different message types. This channel's type is an interface type specific to that channel. To only allow the correct messages to be sent to the channel only the allowed messages "implement" that interface. This was amazingly effective in allowing me to write correct code in what was a complicated jumble of different channels. In fact using the auto-completion provided by my editor the code almost wrote itself. Moreover, the maintainability of the code is improved.<br />
<br />
The only downside is that the implementation looks a bit unusual. This is due to the way Go implements interfaces. You don't explicitly say a type implements an interface; the compiler determines that a type implements an interface because it implements all functions of the interface (with correct parameters and returns values). To allow the compiler to enforce our type-safe channels we need to create an interface type (eg <span style="color: #b45f06;">IProcessor </span>below) with a dummy function (eg <span style="color: #b45f06;">ImplementsProcessor</span>) that all messages for that channel must implement.<br />
<br />
In order to show this in action I include a simple application for conversion between any two different currencies.<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Exchange Rates Example</b></span><br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 240px;">
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">WARNING: This code makes several assumptions about exchange rates that are unrealistic, as anyone who understands exchange rates would atest.</span></div>
<br />
Here is a simple example using this technique. It is a server that receives currency rates from external sources, stores them and can send notifications when the rate changes. This would allow, for example, a subscriber to track the exchange rate between any two currencies as demonstrated below.<br />
<br />
<span style="color: #cc0000;"><span style="color: #cc0000;">EDIT: Here is a link to the full example on the Go Playground, so you can run and play around with it: </span><a href="https://play.golang.org/p/DQAC5lsdX--"><span style="color: blue;">Exchange Rates Example</span></a></span><br />
<br />
<span style="color: #3d85c6;"><b>Channels</b></span><br />
<br />
The sample code uses three different types of channels:<br />
<ul>
<li>Currency channel - receives updates to a currency + requests for a feed of rate updates</li>
<li>Main processor - tracks currencies & hooks up requests to the correct currency channel</li>
<li>Response channels where currency feeds are sent</li>
</ul>
As I said the types of each channel are of different interface types:<br />
<br />
1. <span style="color: #b45f06;">type ICurrency interface { ImplementsCurrency() }</span><br />
2. <span style="color: #b45f06;">type IProcessor interface { ImplementsProcessor() }</span><br />
3. <span style="color: #b45f06;">type IResponse interface { ImplementsResponse() }</span><br />
<br />
Not that the functions (<span style="color: #b45f06;">ImplementsCurrency()</span> etc) don't do nothing other than indicate that a type is intended as a message to a particular type of channel. For example, the NewCurrency type is only intended to be sent to the main processor.<br />
<span style="white-space: pre;"> </span><br />
To indicate this it must have a dummy function called ImplementsProcessor.<br />
<br />
<div style="background-color: #e1e1e1;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">type NewCurrency struct {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ch chan ICurrency // where rate changes are sent</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> name string // name of the currency</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (NewCurrency) ImplementsProcessor() {}</span></div>
<br />
<span style="color: #3d85c6;"><b>Messages</b></span><br />
<span style="white-space: pre;"> </span><br />
In this simple example there are only four different types of messages (structs): <span style="color: #b45f06;">NewCurrency</span>, <span style="color: #b45f06;">NewRate</span>, <span style="color: #b45f06;">CurrencyRequest</span>, <span style="color: #b45f06;">Update</span>.<br />
<br />
As mentioned above, <span style="color: #b45f06;">NewCurrency</span> is sent to the main processor so it can track all the active currencies. It just contains the name of the currency and the channel where the currency update messages (NewRate) are sent.<br />
<br />
A <span style="color: #b45f06;">NewRate </span>message is sent to a currency process. This just says that the exchange rate of the currency has changed relative to some reference currency. The reference currency could be anything - eg. current USD, USD at a certain date, a weighted index, etc - as long as all rates use the same one. Note that the demo below just generates fictitious rate values but in a real application the values could be scraped from some web site or be sent directly from some authority.<br />
<br />
A <span style="color: #b45f06;">CurrencyRequest </span>message is sent by a party who wants to subscribe to rate changes for a currency. It supplies the name of the currency it wants to know about and a channel of <span style="color: #b45f06;">IResponse</span> where the changes to the currency are fed. Typically, the party would request at least 2 currencies so it knows the current exchange rate between the two when either changes.<br />
<br />
Finally, an <span style="color: #b45f06;">Update</span> message is sent to any party who has subscribed to the currency.<br />
<br />
Here are all the channel and message types:<br />
<br />
<div style="background-color: #e1e1e1;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">type (</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> IProcessor interface {</span> <span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">ImplementsProcessor()</span> <span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ICurrency interface {</span> <span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">ImplementsCurrency()</span> <span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> IResponse interface {</span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace; white-space: pre;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">ImplementsResponse()</span> <span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // NewCurrency - new currency available</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> NewCurrency struct {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ch chan ICurrency // where rate changes are sent</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> name string // name of the currency</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // CurrencyRequest asks for updates on a currency's changes</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> CurrencyRequest struct {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> name string // name of currency we want rates for</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ch chan IResponse // where updates are sent</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // NewRate - currency rate has changed</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> NewRate struct {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate float64 // new rate (relative to ref. currency)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Update - response sent whenever the currency rate changes</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> Update struct {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> name string</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate float64</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// ====== IProcessor messages ======</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (NewCurrency) ImplementsProcessor() {}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (CurrencyRequest) ImplementsProcessor() {}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// ====== ICurrency messages ======</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (NewRate) ImplementsCurrency() {}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (CurrencyRequest) ImplementsCurrency() {}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// ====== IResponse messages ======</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (Update) ImplementsResponse() {}</span></div>
<br />
<b><span style="color: #3d85c6;">Processing</span></b><br />
<br />
Processing is easy to understand in this simple example but I will briefly explain. There is one "main processor" that starsts up a go-routine to keep track of all currencies by receiving <span style="color: #b45f06;">NewCurrency </span>messages. It also forwards <span style="color: #b45f06;">CurrencyRequest</span> to the relevant currency processor.<br />
<br />
Each currency has its own currency processor which receives messages through its <span style="color: #b45f06;">ICurrency</span> channel. The <span style="color: #b45f06;">NewRate </span>message simply informs the processor that its rate has changed. The <span style="color: #b45f06;">CurrencyRequest </span>message requests that currency updates are sent for a currency whenever it changes - it supplies a <span style="color: #b45f06;">IResponse </span>channel where the exchange rate updates are sent.<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
// processorCh (singleton) where processor requests are sent</div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">var processorCh chan IProcessor</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func GetMainProcessor() chan<- IProcessor {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if processorCh == nil {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> processorCh = make(chan IProcessor, 100)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Start main processing</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> go func() {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> currencies := make(map[string]*NewCurrency)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> for m := range processorCh {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> switch message := m.(type) {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> case CurrencyRequest:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Forward the request to the specific currency handler</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if pCurrency, ok := currencies[message.name]; ok {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> pCurrency.ch <- message</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> case NewCurrency:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> currencies[message.name] = &message</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Start processing of this currency</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> go func() {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> c := &message</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> feeds := make(map[chan IResponse]struct{})</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate := 0.0</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">for message := range c.ch {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">switch message := message.(type) {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">case NewRate: // new rate against ref. currency</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">rate = message.rate</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">for feed := range feeds {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">feed <- Update{name: c.name, rate: rate}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">case CurrencyRequest:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">feeds[message.ch] = struct{}{}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">if rate > 0 {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">message.ch <- Update{name: c.name, rate: rate}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return processorCh</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span></div>
<br />
<span style="color: #3d85c6;"><b>Test Harness</b></span><br />
<br />
Finally, we have some code to demonstrate the system. This uses the <span style="color: #b45f06;">startRateFeed()</span> function to create a new currency channel and continually send random rate changes to it. The main functions creates some currencies and an <span style="color: #b45f06;">IResponse </span>channel and asks the main processor to send updates for USD and AUD. It then displays the current exchange rate when either of the currencies moves.<br />
<br />
<div style="background-color: #e1e1e1;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// startRateFeed simulates rate updates from an external source</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func startRateFeed(name string, initial float64, </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> delay time.Duration) {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Set up fake currency</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ch := make(chan ICurrency, 10)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> GetMainProcessor() <- NewCurrency{</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ch: ch,</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> name: name,</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> go func() {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate := initial</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> for {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Randomly vary the rate by up to ±0.001 currency units</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate += float64(rand.Intn(21)-10) / 10000</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if rate <= 0 {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate = 0.01 // ensure we stay above zero</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ch <- NewRate{rate: rate}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> time.Sleep(delay)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func main() {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> mp := </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">GetMainProcessor()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Set up fake inputs for a few currencies</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> startRateFeed("AUD", 0.72, 7*time.Second)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> startRateFeed("USD", 1.0, 3*time.Second)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> startRateFeed("NZD", 0.65, 20*time.Second)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Set up conversion for AUD to USD</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> currency1 := "AUD"</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> currency2 := "USD"</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> chReply := make(chan IResponse) // where updates are sent</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> mp <- CurrencyRequest{name: currency1, ch: chReply}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> mp <- CurrencyRequest{name: currency2, ch: chReply}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // Loop getting updates and showing the conversion </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // rate when either currency changes</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> var rate1, rate2 float64</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> for m := range chReply {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> update := m.(Update)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> switch update.name {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> case currency1:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate1 = update.rate</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> case currency2:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> rate2 = update.rate</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">fmt.Printf("1 %s is equal to %.3f %s\n", </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> currency1, rate1/rate2, currency2)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span></div>
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Conclusion</b></span><br />
<br />
Type safety is one of the great things about Go but I have seen a lot of code which loses that benefit by using general interfaces (interface {}). I hope I have shown that you may be able to use more specific interfaces (of channels in this case) for improved type safety.<br />
<br />
In my next post I will enhance the above example to demonstrate some further problems and techniques.<br />
<br />
One problem I did not have time to address is that declaring a method for a type automatically also works for a pointer to that type. I discovered this when I accidentally pass a pointer to a message type rather than the message type itself which caused a confusing bug.<br />
<br />
Another problem, not specific to my technique, is to do with shutting down channels with multiple writers while avoiding writing to a closed channel.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-65596698418015083572018-11-21T15:46:00.004+11:002023-07-01T11:04:39.114+10:00Go Puzzle Solutions<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; font-size: 12px; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US"><span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span style="color: rgba(0, 0, 0, 0);">Here are the answers to </span><a href="https://devmethodologies.blogspot.com/2018/10/go-puzzles-not-interview-questions.html" target="_blank"><span style="color: #2b00fe;">last months puzzles</span></a><span style="color: rgba(0, 0, 0, 0);">.</span></span></div><div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US"><span style="font-size: 14.6667px;"><br /></span></div><div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US"><span style="font-size: 14.6667px;"><span style="color: rgba(0, 0, 0, 0);">[</span><b style="color: windowtext;">Ed (2023/07/01):</b><span style="color: rgba(0, 0, 0, 0);"> Some of these puzzles have more detailed explanations with </span><i style="color: windowtext;">diagrams</i><span style="color: rgba(0, 0, 0, 0);"> in </span><a href="https://docs.google.com/presentation/d/1LeUHLW4i68h3FZ0rT9RSzZ-NnZ8iZ7jmZ-qfri_W8TI/edit?usp=sharing"><span style="color: #2b00fe;">this slide deck</span></a><span style="color: rgba(0, 0, 0, 0);">, which was created for </span><span style="color: #2b00fe;"><a href="https://www.meetup.com/golang-syd/events/294169772/">June 2023 Sydney Go Meetup</a>,</span><span style="color: rgba(0, 0, 0, 0);"> and contain some </span><b style="color: windowtext;">new puzzles</b><span style="color: rgba(0, 0, 0, 0);">.]</span><br /></span>
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="color: windowtext; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><br /></span>
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="color: windowtext; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><b>Please tell me if you find any mistakes.</b></span></div>
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; font-size: 12px; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">1. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">Maps are really just pointers (some people call maps reference types), so <span style="color: #b45f06;">m</span> and </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">mcopy</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> refer to the same map. Since the element with an empty string key has been assigned to twice there are only 3 elements in the map.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">2. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The inbuilt <span style="color: #b45f06;">copy</span> function does not change the length of the destination slice; it just copies until the end of the source or destination. In this case the source is shorter and so the other bytes (and the length) of <span style="color: #b45f06;">s</span> are not changed.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">3. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The first <span style="color: #b45f06;">panic </span>(line 8) is recovered at the first <span style="color: #b45f06;">recover()</span> encountered (line 5) which has its return value printed (ABC). Then another <span style="color: #b45f06;">panic </span>(line 6) occurs and is recovered by the nested <span style="color: #b45f06;">defer</span> (line 2) which has its return value printed (DEF).</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">4. b</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The outer-scope variable <span style="color: #b45f06;">c</span> is captured in the closure passed to </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">IndexFunc</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">()</span>. This contains 'c' which is matched at offset 2 in the string. Hence </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">IndexFunc</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">()</span> returns 2.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">5. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The string is composed of two runes of 3 bytes each. The length of the string is the number of bytes as is the length of the slice of bytes when cast.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">6. a</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">init</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">()</span> functions are executed in the order they are declared so 1 then 2 are written to the channel. The writes do not block because the channel has a buffer size of 2. The <span style="color: #b45f06;">main() </span>function reads and prints the first value sent.</span></span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">7. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The iota has the value zero in the first line and is incremented for every subsequent line until the end of the const. Hence the total would be 0+1+2+3 = 6.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">8. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The slice <span style="color: #b45f06;">s</span> has length of one (2-1) and starts at index one of the array. The <span style="color: #b45f06;">copy()</span> statement only copies to the minimum of the source and destination so only overwrites the array element at index one. Hence the array element at index 2 (43) is unchanged.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">9. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The order that a map is iterated in a for-range loop is unspecified. If element 1 is seen first the first time through the loop it will be deleted and "1 1 " will be printed, then the 2nd time through the loop "2 1 " will be printed (b). If element 2 is seen first then it will not be deleted until the 2nd time through the loop hence "2 2 1 1 " will be printed (c).</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">10. b</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><br />The 3 value slicing is rarely used but allows you to specify the offset of the capacity of the new slice. So b has </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">a length of 2 (2-0) and a capacity of 4 (4-0). The difference between capacity and length is 2.</span></span></span><br />
<span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><br /></span></span></span>
<span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"><span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">If the re-slice did not specify a capacity (<span style="color: #b45f06;">a[0:2]</span>) then it the slice would have a capacity of the underlying array and the answer would be c (5 - 2 = 3).</span></span></span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">11. b</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span><br />
<span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;">This is my favourite trick question (most people think d is the answer). Th</span><span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">ere is a subtle bug that the </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">sync.WaitGroup</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> is passed to the closure by value. Hence the <span style="color: #b45f06;">Wait()</span> method will never return, and the <span style="color: #b45f06;">main()</span> function will just print "B" and exit.</span></span><br />
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><br /></span></span>
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">You should <b>never pass a </b></span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;"><b>WaitGroup</b></span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><b> by value </b>- either capture it within the closure or pass a pointer to it.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> Note that "go vet" will warn you of this problem with this message: <span style="color: #0b5394;">func passes lock by value: sync.WaitGroup contains sync.noCopy</span>.</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">If the defect is fixed then the answer is d, since which go-routine proceeds after Done() is executed and Wait() can proceed is indeterminate. It might still just print "B" is the<span style="color: #b45f06;"> main()</span> function exits and the program stops before the other go-routine has a chance to print "A".</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">12. b</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">Numeric literals have no exact type so <span style="color: #b45f06;">2e2</span>, for example, can be assigned to an <span style="color: #b45f06;">int</span> without a cast. However, they have a "</span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">prefered</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">" type which is the type they take given no constraints. Hence </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">i</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> has type <span style="color: #b45f06;">int </span>whereas <span style="color: #b45f06;">f</span> has type <span style="color: #b45f06;">float64</span>.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">In the 2nd line the 2nd expression is constrained to be of type <span style="color: #b45f06;">float64 </span>because of the type of <span style="color: #b45f06;">f</span>. Similarly, the 3rd expression is of type <span style="color: #b45f06;">int </span>because of the type of </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">i</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The literals in the first expression in the 2nd line are unconstrained but an <span style="color: #b45f06;">int </span>(</span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">preferred</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> type of <span style="color: #b45f06;">200</span>) is trumped by <span style="color: #b45f06;">float64 </span>(the </span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">preferred</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> type of <span style="color: #b45f06;">2e2</span>).</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">13. a</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The <span style="color: #b45f06;">append </span>requires a memory allocation since the new slice has a length of 4 (length of <span style="color: #b45f06;">s</span> plus 3), but the capacity of <span style="color: #b45f06;">s</span> is only 2. </span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The new slice <span style="color: #b45f06;">t</span> has length 4 and capacity of <i>at least</i> 4, but <span style="color: #b45f06;">s</span> is unchanged in length (and value).</span></span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><br /></span>
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">[UPDATE: Note that after an allocation the capacity of the new slice is unspecified, but at least 4, so answers of "1 5", "1 6", etc are also possible. However, the only possible answer of the choices given is a = "1 4"]</span><br />
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">14. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The variable (<span style="color: #b45f06;">a</span>) is an array of 4 elements since the last index specified is 3 (idx+1). Note that the unspecified elements (with indices of 0 and 2) are </span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">initialised</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> to zero.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">15. a </span><span style="font-size: 14.6667px;"> </span><span style="font-size: 14.6667px;">[UPDATE: previous incorrect answer was b]</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">Despite claims to the contrary interfaces are not "reference" types. Any change to <span style="color: #b45f06;">b</span> cannot affect the int <span style="color: #b45f06;">a</span>. The answers c and d can never happen since all parameters passed to </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">fmt.Println</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">()</span> are automatically cast to the <span style="color: #b45f06;">interface{}</span> type and the <u><i>referenced</i></u> value is printed.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">16. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">There is no initialiser on the 2nd and 4th lines so the one from the line above is used. By the 3rd line iota has the value 2 and on the 4th line it's 3. Hence the answer is 0+0+2+3 = 5.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">17. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The first <span style="color: #b45f06;">append </span>does not require a reallocation since the slice passed as the first parameter has length 1 but capacity 2 - so 3 is placed in the underlying array element at index 1. The second <span style="color: #b45f06;">append </span>requires a reallocation so the original underlying array is not touched.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">18. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The type of a map key must be a comparable type so it can't be a slice, map or function type, or a type (struct, array or interface) containing such a non-comparable type. Map keys can be <i>interface </i>types as long as the interface does not contain a non-comparable type.<br /></span><br />
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">In this case the underlying type for the key of the 2nd element added (<span style="color: #b45f06;">m[b]</span>) is a slice. This is not allowed since slices cannot be compared, but because the slice is inside an interface this cannot be determined at compile-time so instead causes a panic at run-time.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">19. c</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">Normally you can't modify a value returned from a map and have it reflected in the map since a copy of the map element is returned. However, in this case the map contains pointers. We don't modify the pointer but the int field of the struct pointed to is incremented from 1 to 2.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">20. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The closure (<span style="color: #b45f06;">a</span>) returns the year for the current time (2018 at time of writing). The call to <span style="color: #b45f06;">Format()</span> returns a string containing the current year as 2 digits (it returns"18" at time of writing) which is then converted to an <span style="color: #b45f06;">int </span>(18). Hence the result is 18-2018 = -2000.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">21. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">fallthrough</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;"> </span>statement can only be used at the end of a case. (If it compiled the answer would be a.)</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">22. b</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The value in a for-range loop is a copy of the slice element. Incrementing it has no effect on the slice.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">23. a</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">When you copy into a slice, no more elements than the original length of the slice are copied. The capacity is irrelevant.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">24. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">Whether the address of a zero-sized object is unique is explicitly not defined for the Go language. But typically this will print true or false.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">25. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">When an interface type is used as a map key the underlying values are compared (type and value). In this case both underlying values are strings with the same value, so <span style="color: #b45f06;">m[a]</span> and <span style="color: #b45f06;">m[b]</span> refer to the same element.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">26. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">In a type-switch the variable assigned from the interface value (in this case<span style="color: #b45f06;"> t</span>) takes the type specified within the code for its <span style="color: #b45f06;">case </span>clause. However, in this case there is a list of types (<span style="color: #b45f06;">int </span>and </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">uint</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">) so it cannot have a specific type and retains the interface type. (If separate <span style="color: #b45f06;">case </span>clauses were </span><span class="ContextualSpellingAndGrammarError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">use</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> for <span style="color: #b45f06;">int </span>and </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">uint</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;"> </span>then the answer would be a.)</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">27. b</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">Casting an integer to a string creates a string with a single rune represented by the integer. In this case the Unicode value 65 is the same as the ASCII value - a capital A.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">28. d</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">Array elements may be initialized by index in this way but in this case <span style="color: #b45f06;">i1</span> and <span style="color: #b45f06;">i3</span> have the same value. The compile sensibly detects that the same element is being set twice and produces an error.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">29. a</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">The type </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">intA</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;"> </span>is a unique type so cannot be mixed in expressions with </span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">int</span>s</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> without a cast. However, the type </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">intB</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;"> </span>is just an alias for <span style="color: #b45f06;">int </span>so the expression <span style="color: #b45f06;">int(a) | b</span> is allowed. Of course, the bit-wise OR operation turns of all bits (<span style="color: #b45f06;">1 | 2</span> = 0).</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">30. c</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;">There are no tricks here, except that you may not </span><span class="SpellingError SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; background-image: url("data:image/gif; background-position: left bottom; background-repeat: repeat-x; border-bottom: 1px solid transparent; margin: 0px; padding: 0px; user-select: text;">realise</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"> that you do not need to wait on the channel (the return value of </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">ctx.Done</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">()</span>) before getting the result from </span><span class="SpellingError SCXO165291458" style="background-color: inherit; background-position: 0% 100%; background-repeat: repeat-x; border-bottom: 1px solid transparent; color: #b45f06; margin: 0px; padding: 0px;">ctx.Err</span><span class="NormalTextRun SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: inherit; margin: 0px; padding: 0px; user-select: text;"><span style="color: #b45f06;">()</span>.</span></span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">31. a</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">Iota is zero in the first line and one in the 2nd, hence the answer is 0+0+2+3 = 5.</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">32. a [UPDATE: previous incorrect answer was d]</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><br /></span></div>
<span face="calibri, calibri_msfontservice, sans-serif" style="background-color: transparent; font-size: 14.6667px;">We are comparing two interfaces one of which contains a string and one of which contains a function. You might expect this to panic since you cannot compare functions (see the answer to question 18 for more information). However, when comparing interfaces the runtime appears to compare the types first and if different gives the values false if the types do not match (as in this case).</span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="background-color: white; clear: both; cursor: text; direction: ltr; margin: 0px; overflow: visible; padding: 0px; position: relative;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"><br /></span></div>
<div style="font-family: "segoe ui", "segoe ui web", arial, verdana, sans-serif; font-size: 12px;">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">Note that I first tried this on Go 1.8 or 1.9 (Windows 64-bit) and believe I got a panic (answer d), but have since not been able to reproduce that behaviour (with any version of Go). I am not sure if this was a bug in the Go runtime that was fixed or I was mistaken.<br /><span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="background-color: transparent; font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></span></div>
</div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">33. a</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US">The string to be printed contains 2 bytes containing the letter 'A' and a byte with the hex value BC. The %q format specifier does more than place double-quotes around the output string it also escapes characters making the string suitable for inserting into Go source code. (If <span style="color: #b45f06;">%s</span> was used instead then c would be the answer.)</span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<span class="TextRun SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" lang="EN-US" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;" xml:lang="EN-US"> </span><span class="EOP SCXO165291458" face=""calibri" , "calibri_msfontservice" , sans-serif" style="font-size: 11pt; line-height: 18px; margin: 0px; padding: 0px;"> </span></div>
</div>
<div class="OutlineElement Ltr SCXO165291458" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: white; clear: both; cursor: text; direction: ltr; font-family: "Segoe UI", "Segoe UI Web", Arial, Verdana, sans-serif; font-size: 12px; margin: 0px; overflow: visible; padding: 0px; position: relative; user-select: text;">
<div class="Paragraph SCXO165291458" lang="EN-US" style="-webkit-tap-highlight-color: transparent; -webkit-user-drag: none; background-color: transparent; color: windowtext; overflow-wrap: break-word; padding: 0px; user-select: text; vertical-align: baseline;" xml:lang="EN-US">
<br /></div>
</div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com2tag:blogger.com,1999:blog-7237530825191390698.post-80974044181401770532018-10-31T17:13:00.000+11:002018-11-21T15:44:18.767+11:00Go PuzzlesHere are a few puzzles intended to help you round out your knowledge of the Go programming language.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Background</span><br />
<br />
In 1983 I had read my copy of K&R from cover to cover (twice I think) and believed I knew everything there was to know about C. I thought K&R (The C Programming Language by Kernighan and Ritchie) was the only book on C that existed but one day I came across another - the C Puzzle Book by Alan Feuer. I bought it and soon discovered that I knew very little about C - such as the myriad possibilities for undefined behavior.<br />
<br />
Luckily Go has greatly limited the prospects of undefined behavior. However, I still think there is room for a selection of puzzles to test your knowledge of the language. Most of puzzles below are the result of discovering something I didn't know in my reading of the excellent "Go Programming Language" by Donovan and Kernighan.<br />
<br />
The questions are in no particular order but I tried to start with easy ones. Don't worry if you get most of them wrong as some are pretty obscure - I'd get a few wrong myself even though I wrote them all!<br />
<div>
<br /></div>
<div>
<span style="color: #3d85c6; font-size: large;">The Questions</span></div>
<br />
<div>
<span style="font-size: x-small;">For brevity most of the puzzles only provide a snippet of Go code. In which case, you can assume that the code is wrapped in a main() function with all relevant imports added.</span></div>
<div>
<ol>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
m := map[string]int{"": 0}<br />
mcopy := m<br />
mcopy["1"] = 1<br />
mcopy["0"] = 0<br />
mcopy[""] = 1<br />
<br />
print(len(m))</div>
</div>
<br />What does this print?<br />a. 1<br />b. 2<br />c. 3<br />d. 4<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
s := []int{1, 2, 3, 4}<br />
copy(s, []int{42})<br />
fmt.Println(s)</div>
</div>
<br />What does this print?<br />a. [42]<br />b. [42 1 2 3 4]<br />c. [1 2 3 4 42]<br />d. [42 2 3 4]<br /> </li>
<li><div style="background-color: #eeeeee; padding: 10px;">
<span style="color: #774400; font-family: "courier" , monospace;">defer func() {</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> defer func() {</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> fmt.Print(recover())</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> }()</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> fmt.Print(recover())</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> panic("DEF")</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">}()</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">panic("ABC")</span></div>
<br />What does this print?<br />a. ABC<br />b. DEF<br />c. ABCDEF<br />d. <nil><br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
c := 'c'<br />
print(strings.IndexFunc("abcdefg", func(r rune) bool {<br />
return r == c<br />
}))
</div>
<br />What does this print?<br />a. -1<br />b. 2<br />c. 3<br />d. compile error: undefined: c<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
s := "世界"
<br />
fmt.Println(len(s), len([]byte(s)))
</div>
<br />What does this print?<br />a. 2 2<br />b. 6 2<br />c. 6 6<br />d. 2 6<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
func init() {<br />
i = make(chan int, 2)<br />
i <- 1<br />
}<br />
<br />
var i chan int<br />
<br />
func init() {<br />
i <- 2<br />
}<br />
<br />
func main() {<br />
fmt.Println(<-i)<br />
}</div>
<br />What does this print?<br />a. 1<br />b. 2<br />c. prints nothing and never terminates<br />d. compilation error: init redeclared in this block<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
const (
<br />
a = iota<br />
b<br />
c<br />
d<br />
)<br />
fmt.Println(a+b+c+d)
</div>
<br />What does this print?<br />a. 0<br />b. 4<br />c. 6<br />d. 10<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
a := [...]int{41, 42, 43, 44, 45}
<br />
s := a[1:2]
<br />
copy(s, []int{1, 2, 3})
<br />
fmt.Println(a[2])
</div>
<br />What does this print?<br />a. 2<br />b. 3<br />c. 42<br />d. 43<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
m := map[int]int{1: 1, 2: 2}
<br />
for k := range m {<br />
if k == 1 {
<br />
delete(m, k)<br />
}<br />
fmt.Print(k, len(m), " ")
<br />
}</div>
<br />What does this print?<br />a. 1 1<br />b. 1 1 2 1<br />c. 2 2 1 1<br />d. either b or c<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
a := []int{0, 1, 2, 3, 4}
<br />
b := a[0:2:4]
<br />
fmt.Println(cap(b) - len(b))
</div>
<br />What does this print?<br />a. 0<br />b. 2<br />c. 3<br />d. 4<br /> </li>
<li><div style="background-color: #eeeeee; padding: 10px;">
<span style="color: #774400; font-family: "courier" , monospace;">var wg sync.WaitGroup</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">wg.Add(1)</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">go func(wg sync.WaitGroup) {</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> wg.Wait()</span><br />
<span style="color: #774400; font-family: "courier" , monospace;"> print("A")</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">}(wg)</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">wg.Done()</span><br />
<span style="color: #774400; font-family: "courier" , monospace;">print("B")</span></div>
<br />What does this print?<br />a. AB<br />b. B<br />c. BA<br />d. any one of the above<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
i, f := 200, 2e2<br />
x, y, z := 200+2e2, 200+f, i+2e2<br />
fmt.Printf("%T %T %T", x, y, z)
</div>
<br />What does this print?<br />a. int float64 int<br />b. float64 float64 int<br />c. float64 float64 float64<br />d. None of the above<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
s := []int{1, 2, 3}[1:2]<br />
t := append(s, 4, 5, 6)<br />
fmt.Println(len(s), cap(t))</div>
</div>
<br />What does this print?<br />a. 1 4<br />b. 2 5<br />c. 4 4<br />d. 4 6<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
const idx = 2<br />
a := [...]int{idx: 1, idx+1: 2}<br />
fmt.Println(a[3])</div>
</div>
<br />What does this print?<br />a. 0<br />b. 1<br />c. 2<br />d. compilation error: invalid array index 3<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
a := 1<br />
var b interface{} = a<br />
a = 2<br />
fmt.Println(b)</div>
</div>
<br />What does this print?<br />a. 1<br />b. 2<br />c. (interface {})(1)<br />d. (interface {})(2)<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
const (<br />
a = 0<br />
b<br />
c = iota<br />
d<br />
)<br />
fmt.Println(a+b+c+d)</div>
</div>
<br />What does this print?<br />a. 1<br />b. 2<br />c. 5<br />d. 6<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
a := [...]int{1, 2}<br />
_ = append(a[:1], 3)<br />
_ = append(a[:1], 4, 5)<br />
fmt.Println(a[1])</div>
</div>
<br />What does this print?<br />a. 0<br />b. 2<br />c. 3<br />d. 4<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
s := bytes.NewBufferString("string")<br />
a := s.String()<br />
b := s.Bytes()<br />
m := make(map[interface{}]int)<br />
m[a] = 1<br />
m[b] = 2<br />
log.Println(m[a])</div>
</div>
<br />What does this print?<br />a. 1<br />b. 2<br />c. compile error: invalid map key<br />d. panics at run-time<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
m := make(map[int]*struct{ i int })<br />
m[3] = &struct{ i int }{1}<br />
v := m[3]<br />
v.i++<br />
fmt.Println(m[3].i)</div>
</div>
<br />What does this print?<br />a. 0<br />b. 1<br />c. 2<br />d. 3<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
a := time.Now().Year<br />
b, _ := strconv.Atoi(time.Now().Format("06"))<br />
fmt.Println(b - a())</div>
</div>
<br />What does this print?<br />a. 6<br />b. 0<br />c. -2000<br />d. 18 (current year this century)<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
i := 2<br />
switch i {<br />
case 2:<br />
if i % 2 == 0 {<br />
fallthrough<br />
}<br />
i = 6<br />
case 3:<br />
i++<br />
fallthrough<br />
default:<br />
i++<br />
}<br />
print(i)</div>
</div>
<br />What does this print?<br />a. 4<br />b. 5<br />c. 6<br />d. compile error: fallthrough statement out of place<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
s := []int{10, 12, 14}<br />
for _, v := range s {<br />
v++<br />
}<br />
fmt.Println(s[1])</div>
</div>
<br />What does this print?<br />a. 11<br />b. 12<br />c. 13<br />d. 14<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
s := []int{1, 2, 3, 4}<br />
t := make([]int, 2, 3)<br />
copy(t, s)<br />
fmt.Println(t)</div>
</div>
<br />What does this print?<br />a. [1 2]<br />b. [1 2 3]<br />c. [1 2 3 4]<br />d. [0 0 3 4]</li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
a := struct{}{}<br />
b := struct{}{}</div>
<div style="padding: 10px;">
fmt.Printf("%t", &a == &b)</div>
</div>
<br />What does this print?<br />a. false<br />b. true<br />c. bool<br />d. the exact behaviour of this code is undefined<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
var a, b interface{}</div>
<div style="padding: 10px;">
a = "str" + "ing"<br />
b = "string"</div>
<div style="padding: 10px;">
m := make(map[interface{}]int)<br />
m[a] = 1<br />
m[b] = 2</div>
<div style="padding: 10px;">
print(m[a])</div>
</div>
<br />What does this print?<br />a. 0<br />b. 1<br />c. 2<br />d. compile error: invalid map key<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
var t interface{} = 1</div>
<div style="padding: 10px;">
switch t := t.(type) {<br />
case int, uint:<br />
fmt.Println(reflect.TypeOf(&t))</div>
<div style="padding: 10px;">
default:<br />
print("default")<br />
}</div>
</div>
<br />What does this print?<br />a. *int<br />b. *uint<br />c. default<br />d. *interface{}<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
fmt.Printf("%q\n", string(65))</div>
</div>
<br />What does this print?<br />a. "65"<br />b. "A"<br />c. "\x41"<br />d. "�"<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
const i1, i2, i3 = 2, 3, 2<br />
a := [...]int{i1: i1, i2: i2, i3: i3}</div>
<div style="padding: 10px;">
print(len(a))</div>
</div>
<br />What does this print?<br />a. 2<br />b. 3<br />c. 4<br />d. compile error: duplicate index in array literal: 2<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
type intA int<br />
type intB = int<br />
var a intA = 1<br />
var b intB = 2<br />
print(int(a) | b)</div>
</div>
<br />What does this print?<br />a. 0<br />b. 1<br />c. 3<br />d. compile error: invalid operation: int(a) | b (mismatched types int and intB)<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
ctx, cancel := context.WithCancel(context.Background())</div>
<div style="padding: 10px;">
cancel()</div>
<div style="padding: 10px;">
fmt.Println(ctx.Err())</div>
</div>
<br />What does this print?<br />a. <nil><br />b. deadline exceeded<br />c. context canceled<br />d. does not print anything but causes a panic at run-time<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
const (<br />
a, b = iota, iota<br />
c, d = iota+1, iota+2<br />
)</div>
<div style="padding: 10px;">
print(a+b+c+d)</div>
</div>
<br />What does this print?<br />a. 5<br />b. 6<br />c. 7<br />d. 9<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
<div style="padding: 10px;">
var a, b interface{}<br />
a = "main"<br />
b = main</div>
<div style="padding: 10px;">
fmt.Printf("%t\n", a == b)</div>
</div>
<br />What does this print?<br />a. false<br />b. true<br />c. compile error: invalid interface type<br />d. panics at run-time<br /> </li>
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
fmt.Printf("%q", "A\xbc")</div>
<br />What does this print?<br />a. "A\xbc"<br />b. A<br />c. A�<br />d. "Abc"<br />
</li>
<!--
<li><div style="background-color: #eeeeee; color: #774400; font-family: "courier" , monospace; padding: 10px;">
{
}
</div>
<br />
What does this print?<br />
a. <br />
b. <br />
c. <br />
d. <br />
</li>
-->
</ol>
</div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com2tag:blogger.com,1999:blog-7237530825191390698.post-60345381223364684052018-10-02T16:03:00.000+10:002018-10-02T16:03:11.174+10:00Go Error Handling – Using ClosuresThe Go 2 Error handling draft design was released recently (see <a href="https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md"><span style="color: blue;">Error Handling Overview</span></a>). I took great interest in it as it is similar to my own proposal made last year (see <a href="http://devmethodologies.blogspot.com/2017/10/improving-go-error-handling.html"><span style="color: blue;">Improving Go Error Handling</span></a>) but goes a step further by adding "handlers".<br />
<br />
I like the reasoning behind handlers but I believe something better is needed. Handlers have been discussed at length in the feedback page (see <a href="https://github.com/golang/go/wiki/Go2ErrorHandlingFeedback"><span style="color: blue;">wiki feedback page</span></a>) so I won't add to that noise. [If you have not read any of the other feedback then basically people find handlers confusing - both conceptually and in use, especially if chained.]<br />
<br />
<span style="color: #3d85c6; font-size: large;">Proposal – using Closures </span><br />
<br />
Instead of little bits of code in <span style="color: #b45f06;">handle </span>statements why not simply use the existing Go facility of closures. A closure could be provided for error-handling of a specific expression by putting its name in brackets after the <span style="color: #b45f06;">checked </span>keyword. All such error-handling closures would take one (<span style="color: #b45f06;">error</span>) parameter and return an <span style="color: #b45f06;">error </span>value.<br />
<br />
As in the original draft design, a "default" handler is provided. This is used if the <span style="color: #b45f06;">check </span>keyword does not specify a closure. The "default" handler would be simply implemented as:<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func defaultHandler(err error) error { return err }</div>
<br />
The advantages to this are:<br />
<ul>
<li>it is clearer about where an error for any specific expression is handled </li>
<li>handler "chaining" is still possible (see example below)</li>
<li>closures make chaining more obvious</li>
<li>closures provide even more flexibility than handlers/chaining</li>
<li>error-handling code can be easily separated so as not to obscure the code </li>
<li>but it is still easy to trace how the error is handled if necessary</li>
<li>error handling code can be moved outside the function and even re-used </li>
</ul>
Here is the <span style="color: #b45f06;">CopyFile()</span> example from the <a href="https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md"><span style="color: blue;">Error Handling Overview</span></a> done in this way:<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func CopyFile(src, dst string) error {<br />
eMess := func(err error) error {<br />
return fmt.Errorf("copy %s %s: %v", src, dst, err)<br />
}<br />
<br />
r := check(eMess) os.Open(src)<br />
defer r.Close()<br />
w := check(eMess) os.Create(dst)<br />
<br />
eClose := func(err error) err {<br />
w.Close()<br />
os.Remove(dst)<br />
return eMess(err)<br />
}<br />
<br />
check(eClose) io.Copy(w, r)<br />
check(eClose) w.Close()<br />
return nil<br />
}</div>
<br />
<span style="color: #3d85c6; font-size: large;">Further Proposal – Check Statement </span><br />
<br />
A further idea is to also allow <span style="color: #b45f06;">check </span>to work as a statement. Enclosing statements in a check statement would allow the same check operation to be applied to any contained function calls that returned an error as the last returned value. Using the same example this could be used this way:<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func CopyFile(src, dst string) error {<br />
eMess := func(err error) error {<br />
return fmt.Errorf("copy %s %s: %v", src, dst, err)<br />
}<br />
check(eMess) {<br />
r := os.Open(src)<br />
defer r.Close()<br />
w := os.Create(dst)<br />
}<br />
<br />
eClose := func(err error) err {<br />
w.Close()<br />
os.Remove(dst)<br />
return eMess(err)<br />
}<br />
check(eClose) {<br />
io.Copy(w, r)<br />
w.Close()<br />
}<br />
return nil<br />
}</div>
<span style="color: #3d85c6; font-size: large;"><br /></span>
<span style="color: #3d85c6; font-size: large;">Separating Error Handling Code </span><br />
<br />
Note that the closure used with the <span style="color: #b45f06;">check </span>statement could be an expression evaluating to a function (just as happens with the <span style="color: #b45f06;">defer </span>statement). That is, it could be a function call returning a closure. This allows all the error-handling code to be hived off to another function where it is less distracting.<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func CopyFile(src, dst string) error {<br />
var w *File<br />
check(genErr(src, dst, w)) {<br />
r := os.Open(src)<br />
defer r.Close()<br />
w = os.Create(dst)<br />
io.Copy(w, r)<br />
w.Close()<br />
w = nil<br />
}<br />
return nil<br />
}<br />
<br />
func genErr(src, dst string, w *os.File) func(err error ) error {<br />
return func(err error ) error {<br />
if w != nil {<br />
// output file was opened so close and remove it<br />
w.Close()<br />
os.Remove(dst)<br />
}<br />
return fmt.Errorf("copy %s %s: %v", src, dst, err)<br />
}<br />
}</div>
<br />
<span style="color: #3d85c6; font-size: large;">Summary</span><br />
<br />
Using closures instead of adding the new feature of handlers fits better with how Go currently works and makes use of the Go's wonderful feature of closures.<br />
<br />
I'd like to thank Rob Pike for speaking at the Sydney Go Meetup last Thursday. His talk inspired me to think further about Go error-handling and write this post. Go is by far the least annoying language I have ever used and hopefully the addition of an improved error handling facility will make it even less so.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-27411474297265374472017-11-05T10:31:00.001+11:002017-12-02T18:10:16.539+11:00Active Object in GoIn Go, it is very easy to accidentally access the same data from different go-routines creating a race condition. Conventionally, you avoid this sort of problem with a mutex; and, in fact, you can easily do this in Go using sync.Mutex.<br />
<br />
A way that is often better, and preferred in Go, is to simply <i>avoid </i>accessing the data from different go-routines at the same time. One way is to send messages (through a channel) to a <b><i>confining</i></b> go-routine responsible for all access and control of the data. By confining all access to a single go-routine no locks are required.<br />
<br />
You can also confine use of a value by only using it within one go-routine at a time. This is idiomatically done in Go by transferring control of the variable through a channel, but I won't discuss that here as there are plenty of other articles about it. On another note, there are "low level" ways to do "lock-free" concurrency, using atomic operations, but that will have to wait for another time.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Avoiding Locks</b></span><br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 240px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">“the main advantage<br />is that it simplifies<br />writing the code”</span></div>
<br />
So what is the advantage of avoiding locks? Well, a great deal has been written about that (do a search on Google :), some of it misleading. In my opinion the main advantage is that it simplifies writing the code, by not getting side-tracked with other issues like race conditions. Using mutexes, in complex scenarios, is notorious for retaining subtle race conditions, or potential deadlocks or just performance problems such as unintentionally holding a lock while blocking on I/O.<br />
<br />
Lock contention is often cited as a major advantage of avoiding locks but that is not really the issue. After all, using a confining go-routine (as described above) replaces lock contentions with contention for use of the go-routine. In fact proper use of locks is often more efficient than channels; it's just that it usually involves convoluted and/or repetitive code. For example, this is a typical scenario using locks:<br />
<ol>
<li>lock</li>
<li>check "something"</li>
<li>unlock</li>
<li>do a lengthy operation based on knowledge obtained at 2</li>
<li>lock</li>
<li>check "something" again (repeating test at 2)</li>
<li>update data using results at 4 (if "something" hasn't changed)</li>
<li>unlock</li>
</ol>
However, there <i>are</i> some performance advantages. First, if many threads block on mutex(es) then thread-switching overhead becomes important. Even though the time for thread-switching is only measured in microseconds, if you have thousands of threads it can all add up. Of course, using go-routines lessens this effect, since Go multiplexes them onto a small numbers of threads, but it may still be significant.<br />
<br />
Further, I think Go tries to run go-routines on the same core each time, which means that a confining go-routine may be better at maintaining the CPU cache which could have large performance benefits.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Active Object</b></span><br />
<br />
A useful refinement of the confining go-routine is something that goes by many names but possibly the most common is the <b><i>Active Object Concurrency Pattern</i></b>. It is often used in server software involving a lot of simultaneous connections where the overhead of using a thread for every connection is too onerous. I first encountered this with Boost ASIO - the excellent C++ asynchronous I/O library. (Thanks Leon for introducing me to this and explaining it.)<br />
<br />
However the code for Boost ASIO is complex, since it needs to create its own light-weight "co-routines" (called strands) to multiplex use of threads. I wanted to do something similar in Go and I was amazed to find no advice on how to do this. It should be much simpler since Go provides all the requisite parts: <b>go-routines</b> (rather like strands), and <b>channels </b>of <b>closures</b>.<br />
<br />
Active Object in Go can be implemented by a go-routine that reads closures from a channel (<span style="color: #b45f06;">chan func()</span> ) and executes them. This simple system means that all the closures, containing the code that accesses the data, are run on the same go-routine in the order they are posted to the channel. I guess the best way for you to understand this is with an example.<br />
<br />
My example uses the quintypical example of concurrent coding - the bank account. First, we look at a race condition and how to fix it with a mutex, then using an Active Object. Of course, there are a few complications and things to be aware which I also explain and demonstrate in the code below.<br />
<br />
Note that later code examples make heavy use of anonymous functions (closures), even nesting them. If you are unfamiliar with how they work you may need to read up on them first.<br />
<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Race Example</span></b><br />
<br />
Here is the code for a poorly-featured bank account that only allows deposits. Note that I could have written the <span style="color: #b45f06;">Deposit() </span>function more simply in one line (<span style="color: #b45f06;">ac.bal += amt</span>), but the code below is designed to trigger the race condition, which is there anyway, but the delay caused by the sleep should expose it. (This is one of the biggest problems with race conditions - they may be lurking but invisible - which is why you should get into the habit of using the Go Race Detector.)<br />
<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
type (</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
Money int64 // cents</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
Account struct {</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
bal Money</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
}</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">const Dollars Money = 100 // 100 cents to the dollar</span><br />
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
// NewAccount creates a new account with bonus $100.</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
func NewAccount() *Account {</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
return &Account{bal: 100 * Dollars}</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
}</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
// Deposit adds money to an account.</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
func (ac *Account) Deposit(amt Money) {</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
current := ac.bal</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
time.Sleep(1*time.Millisecond)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
ac.bal = current + amt</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
}
</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
func (ac Account) Balance() Money { return ac.bal }</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br />
<br /></div>
</div>
Now let's do a few <b>concurrent </b>deposits. Note that I tested all this code in a single (<span style="color: #b45f06;">main</span>) package. If you want to try it you could move all the "account" code to a separate package (eg <span style="color: #b45f06;">bank</span>), but then you need to call the function to create a new account as <span style="color: #b45f06;">bank.NewAccount()</span>.<br />
<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
ac := NewAccount()</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<b>go</b> ac.Deposit(1000 * Dollars)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<b>go</b> ac.Deposit(200 * Dollars)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
time.Sleep(100*time.Millisecond)</div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> fmt.Printf("Balance: $%2.2f\n", ac.Balance()/100.0)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
If you run the above code you will be disappointed to find that one of the deposits has gone missing. The deposits are run on separate go routines causing a race condition on <span style="color: #b45f06;">bal</span>.<br />
<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Mutex Example</span></b><br />
<br />
Luckily, this is easily fixed using a mutex to protect concurrent access to <span style="color: #b45f06;">bal</span>. We add a mutex to every account since if we had just one mutex for all accounts that would create a contention problem if many accounts were being updated at the same time.<br />
<br />
<br />
<div style="background-color: #e1e1e1; font-family: "courier new", courier, monospace;">
<div style="color: #b45f06;">
type (</div>
<div style="color: #b45f06;">
Account struct {</div>
<div style="color: #b45f06;">
bal Money</div>
<span style="color: #b45f06;"> </span><span style="color: red;">mutex sync.Mutex</span><br />
<div style="color: #b45f06;">
}</div>
<div style="color: #b45f06;">
)</div>
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
// Deposit adds money to an account.</div>
<div style="color: #b45f06;">
func (ac *Account) Deposit(amt Money) {</div>
<span style="color: red;"> ac.mutex.Lock()</span><br />
<span style="color: red;"> defer ac.mutext.Unlock()</span><br />
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
current := ac.bal</div>
<div style="color: #b45f06;">
time.Sleep(1*time.Millisecond)</div>
<div style="color: #b45f06;">
ac.bal = current + amt</div>
<div style="color: #b45f06;">
}</div>
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
// Balance returns funds available.</div>
<div style="color: #b45f06;">
func (ac *Account) Balance() Money {</div>
<span style="color: red;"> ac.mutex.Lock()</span><br />
<span style="color: red;"> defer ac.mutext.Unlock()</span><br />
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
return ac.bal</div>
<div style="color: #b45f06;">
}</div>
<div style="color: #b45f06;">
<br />
<br /></div>
</div>
Note that <span style="color: #b45f06;">Balance()</span> now takes a<b><i> pointer receiver</i></b>, otherwise we would only be locking a copy of the mutex. We have to lock the mutex in the <span style="color: #b45f06;">Balance()</span> function even though it only reads from the value since there can be concurrent write operations. (If there are lots of reads and very few writes then a <span style="color: #b45f06;">sync.RWMutex</span> may be better than a <span style="color: #b45f06;">sync.Mutex</span> but that is another story.)<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Active Object Example</b></span><br />
<br />
OK that avoids the race condition by using a mutex, but how do we do this using the Active Object pattern? First, instead of a mutex we use a channel of functions. We also need to start a go-routine for each account in the <span style="color: #b45f06;">NewAccount()</span> function, which reads from the channel and runs the functions. Finally, instead of updating <span style="color: #b45f06;">ac.bal </span>directly in the Deposit() function we wrap the code in a <b><i>closure</i></b> (lambda function) and post this closure onto the account channel so that the account's go-routine will process it when it gets a chance.<br />
<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
type (</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
Account struct {</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
bal Money</div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> </span><span style="color: red;">ch chan<- func()</span></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
}</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func NewAccount() *Account {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">ch := make(chan func())</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> <b>go</b> func() {</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> for f := range ch {<span style="white-space: pre;"> </span>f() }</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> }()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return &Account{bal: 100*Dollars, </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">ch: ch</span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<div style="font-family: "courier new", courier, monospace;">
<br /></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
// Deposit adds money to an account.</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
func (ac *Account) Deposit(amt Money) {</div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: red;"> ac.ch <- func() {</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> current := ac.bal</span></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
time.Sleep(1*time.Millisecond)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
ac.bal = current + amt</div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: red;"> }</span></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
}</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br />
<br /></div>
</div>
Note that the unnamed function created in <span style="color: #b45f06;">Deposit()</span> and posted onto the account's channel is a closure (or lambda). Closures have the useful ability to capture variables from their enclosing scope (in this case <span style="color: #b45f06;">ac.bal </span>and <span style="color: #b45f06;">amt</span>).<br />
<br />
Moreover if you make <span style="color: #b45f06;">ch</span> into a <b><i>buffered channel</i></b>, then the account can handle multiple concurrent deposits without ever blocking the calls to <span style="color: #b45f06;">Deposit()</span>. This means that transient spikes in activity on the account will be handled smoothly. Of course, a sustained onslaught of deposits, sent faster than they can be processed will eventually cause blocking when the channel buffer becomes full.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Returning Values</b></span><br />
<br />
You may have noticed that the above code does not include a <span style="color: #b45f06;">Balance()</span> method. Before showing the code for <span style="color: #b45f06;">Balance()</span>, I need to explain how to "return" a value; because the closures are invoked asynchronously you can't simply use a function that returns a value. Even for methods that only update something we may want to return an error to indicate that something went wrong.<br />
<br />
So how do we do it? We simply pass in a callback function (probably a closure) that is called when the operation completes (or fails with an error).<br />
<br />
In the following code I have implemented the <span style="color: #b45f06;">Balance()</span> method but I have also replaced the <span style="color: #b45f06;">Deposit()</span> method with <span style="color: #b45f06;">Add()</span> since we are going to use it for withdrawals (allowing for negative amounts) too. Withdrawals may generate an error if there are insufficient funds in the account, so we pass a callback which can "return" an error.<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;">// Adds transfers money to/from an account.</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;">func (ac *Account) </span><span style="color: red;">Add</span><span style="color: #b45f06;">(amt Money, </span><span style="color: red;">callback func(error)</span><span style="color: #b45f06;">) {</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> ac.ch <- func() {</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> </span><span style="color: red;">if ac.bal + amt < 0 {</span></div>
<span style="color: red;"><span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">callback(fmt.Errorf("insuff. funds %v for w/d %v",</span></span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> ac.bal, amt))</span><br />
<div style="font-family: "courier new", courier, monospace;">
<span style="color: red;"> return</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: red;"> }</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> ac.bal </span><span style="color: #b45f06;">+</span><span style="color: #b45f06;">= amt</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">callback(nil)</span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> // successful transfer</span><br />
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> }</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;">}</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"><br /></span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;">// Balance provides funds available.</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;">func (ac *Account) Balance(</span><span style="color: red;">callback func(Money)</span><span style="color: #b45f06;">) {</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> ac.ch <- func() {</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> callback(ac.bal)</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> }</span></div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;">}</span></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
</div>
<br />
Now here is some code that makes two deposits and attempts a very large withdrawal. Notice that for the deposits we provide a callback (closure) that does nothing - passing a +ve amount means the operation cannot fail so we ignore the possibility of an error. For the withdrawal, we check if there was an error and just print it out.<br />
<br />
<div style="background-color: #e1e1e1;">
<br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac := NewAccount()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.Add(1000 * Dollars, func(error) {} )</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.Add(200 * Dollars, func(error) {} )</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.Add(-1e6 * Dollars, func(err error) {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if err != nil { fmt.Println(err) }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> })</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.Balance(func(bal Money) {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> fmt.Printf("Balance: $%v\n", bal/100)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> })</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> time.Sleep(100*time.Millisecond)</span><br />
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
</div>
<br />
The first thing you may have noticed is that we don't have the keyword <span style="color: #b45f06;"><b>go</b> </span>before the call to <span style="color: #b45f06;">ac.Add(), </span>as we did above for <span style="color: #b45f06;">ac.Deposit()</span>. This is not necessary as most of the <span style="color: #b45f06;">Add()</span> function's code has been made asynchronous anyway. That is, the actual work is done in a closure posted onto the account's channel (for execution by the account's go-routine) allowing <span style="color: #b45f06;">Add()</span> to return almost immediately.<br />
<br />
Notice also the call to <span style="color: #b45f06;">Sleep()</span> in the final line of code which is simply there to prevent the program exiting immediately. If you run the above in a <span style="color: #b45f06;">main()</span> function you may not see any messages. When <span style="color: #b45f06;">main()</span> returns the program ends and all active go-routines are silently terminated. So the calls to <span style="color: #b45f06;">Println()</span>, executed in the account's go-routine may not get a chance to execute. Later I will look at how to wait for all pending operations on an account to complete.<br />
<br />
A crucial thing to remember here is that the callbacks are run on the account's go-routine. This is important to keep this in mind since it is <i>very</i> easy to access a variable from the caller's go-routine in the callback. . If you need to send information back to the posting go-routine the callback can post to another Active Object channel as we will see.<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">“if you perform<br />a lengthy operation<br />... in the callback ...<br />delay other operations<br />… even cause deadlock”</span></div>
<br />
Another important thing to remember is that if you perform a lengthy operation, or an operation that may block, in the callback then you will delay other operations on the account or even cause deadlock. In the example code above, I only call <span style="color: #b45f06;">fmt.Printf()</span> inside the callback but even that may be too much for a server that is handling hundreds of thousands of requests per second.<br />
<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Transfers between Accounts</span></b><br />
<br />
We have basic account features but more advanced features can introduce pitfalls to be aware of. Here is the code for a method to transfer funds between accounts.<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// WARNING: This code has problems</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// TransferTo moves funds between accounts.</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (ac *Account) TransferTo(to *Account, amt Money, </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback func(error)) {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.ch <- func() {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if amt > ac.bal {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback(fmt.Errorf("Insuff. funds %v for tfr %v",</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal, amt))</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal -= amt</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> to.Add(amt, callback)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<br />
To understand what is happening here you need to remember that each account has its own go-routine. The code inside the above closure is executed on the "from" account's go-routine, the end of which calls <span style="color: #b45f06;">to.Add()</span> which posts to the "to" account's go-routine. The third parameter (<span style="color: #b45f06;">callback</span>) to <span style="color: #b45f06;">TransferTo() </span>is effectively a pointer to a function that is "captured" in the closure and passed on to <span style="color: #b45f06;">to.Add()</span> whence it is again captured and called to process the result of the final <span style="color: #b45f06;">Add()</span>.<br />
<br />
However, there are two problems with this code. First, you should <b>not</b> be able to transfer out more funds than are available (ie we need to check that <span style="color: #b45f06;">-amt <= to.bal</span>). The second problem is due to possible deadlocks - eg if two transfers are done simultaneously in opposite directions then each account may block the other - but we'll address that problem later.<br />
<br />
How would we fix the first problem? My first thought was something like this:<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="font-family: "courier new", courier, monospace;">
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// WARNING: This code has worse problems</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// TransferTo moves funds between accounts.</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (ac *Account) TransferTo(to *Account, amt Money, </span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback func(error)) {</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.ch <- func() {</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if amt > ac.bal {</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback(fmt.Errorf("Insuff. funds %v for tfr %v",</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal, amt))</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> } </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">else if amt < 0 && -amt > to.bal {</span><br />
<span style="color: red;"><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span> callback(fmt.Errorf("Insuff. funds %v for tfr %v",</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> to.bal, -amt))</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> return</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal -= amt</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> to.Add(amt, callback)</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
</div>
<br />
Can you see a problem here? If not, think about which go-routine is used to run the above code. All the code inside the closure (including the<span style="color: red;"> new code in red</span>) runs on the <span style="color: #b45f06;">ac</span> account's go-routine, but it accesses <span style="color: #b45f06;">to.bal</span>, access to which should be <i><b>confined </b></i>to the<span style="color: #b45f06;"> to</span> account's go-routine. (Remember that each account has it's own go-routine which is the only place where that account's <span style="color: #b45f06;">bal</span> should be used.)<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="font-family: "courier new", courier, monospace;">
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// WARNING: There is still a problem</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">// TransferTo moves funds between accounts.</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (ac *Account) TransferTo(to *Account, amt Money, </span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback func(error)) {</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.ch <- func() {</span></div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> if amt < 0 {</span><br />
<span style="color: red;"><span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">to.TransferTo(ac, -amt, callback)</span></span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> return</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<div style="color: #b45f06;">
if amt > ac.bal {</div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback(fmt.Errorf("Insuff. funds %v for tfr %v",</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal, amt))</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal -= amt</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> to.Add(amt, callback)</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
</div>
<br />
This fixes the problem with accessing <span style="color: #b45f06;">to.bal</span> on the wrong go-routine but as I mentioned before there is also a deadlock problem.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Deadlock</b></span><br />
<br />
The first thing to note is that a channel in go has a fixed size; this means that any call to <span style="color: #b45f06;">Add()</span>, <span style="color: #b45f06;">Balance() </span>or <span style="color: #b45f06;">Transfer()</span> will block if the channel is full. If other concurrent requests can be posted to the accounts then the "to" account may be blocked waiting for the <span style="color: #b45f06;">ac.Transfer()</span> request to be posted which then blocks the "ac" account in the call to <span style="color: #b45f06;">to.Add()</span>. This causes a mutual deadlock between the two accounts. A simpler scenario is where an account posts to its own channel causing itself to deadlock.<br />
<br />
A solution to these problems is just to fire up another go routine like this.<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="font-family: "courier new", courier, monospace;">
<div style="color: #b45f06;">
<br /></div>
<div style="color: #b45f06;">
// TransferTo moves funds between accounts.</div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func (ac *Account) TransferTo(to *Account, amt Money, </span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback func(error)) {</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.ch <- func() {</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> if amt < 0 {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #b45f06;"> </span><span style="color: red;">go </span></span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">to.TransferTo(ac, -amt, callback)</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<div style="color: #b45f06;">
if amt > ac.bal {</div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> callback(fmt.Errorf("Insuff. funds %v for tfr %v",</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal, amt))</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> ac.bal -= amt</span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">go </span><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">to.Add(amt, callback)</span><br />
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div style="color: #b45f06;">
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
</div>
<br />
This prevents <span style="color: #b45f06;">TransferTo()</span> from blocking and avoids the deadlock. The disadvantage is that we have no guarantees about when the request will be posted if the account channel is overloaded. In this case it may mean there is a delay between the "ac" account being debited and the "to" account being credited. In this example it is not a problem since the funds will eventually be transferred.<br />
<br />
A solution that preserves the order of posted requests is to have two channels: one for external requests and one for priority requests (see <span style="color: red;">priChan</span> below) posted by an account to itself or to another account.<br />
<br />
<div style="background-color: #e1e1e1;">
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
type (</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
Account struct {</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
bal Money</div>
<div style="font-family: "courier new", courier, monospace;">
<span style="color: #b45f06;"> pubChan, </span><span style="color: red;">priChan</span><span style="color: #b45f06;"> chan<- func()</span></div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
}</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
)</div>
<div style="color: #b45f06; font-family: "courier new", courier, monospace;">
<br /></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">func NewAccount() *Account {</span><br />
<span style="color: #b45f06;"><span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> pub</span><span style="color: red; font-family: "courier new" , "courier" , monospace;"> := make(chan func(), 2)</span></span><br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #b45f06;"> </span><span style="color: red;">pri</span></span><span style="color: red; font-family: "courier new" , "courier" , monospace;"> := make(chan func(), 20) // "private" chan</span></div>
<div>
<span style="color: #b45f06;"><span style="color: red; font-family: "courier new" , "courier" , monospace;"><br /></span></span></div>
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> <b>go</b> func() {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> for {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">if len(pri) > 0 {</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> f := <- pri</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> f()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> } else {</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> select {</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> case f := <- pri:</span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> f()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> case f := <- pub:</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> f()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }()</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> return &Account{</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> bal: 100*Dollars, </span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> pubChan: pub, </span><br />
<span style="color: red; font-family: "courier new" , "courier" , monospace;"> priChan: pri,</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="color: #b45f06; font-family: "courier new" , "courier" , monospace;">}</span><br />
<div style="font-family: "courier new", courier, monospace;">
<br /></div>
</div>
<br />
The idea is not to have any "circular" posts - that is any closures posted to a channel should never end up posting back to the same channel. In this way deadlock is not possible.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Conclusion</b></span><br />
<br />
I hope I have demonstrated how easy it is to use the <b>Active Object Concurrency Pattern</b> in Go. As long as you understand how it works and are aware of the pitfalls it provides a simpler, and possibly more efficient, solution than using mutexes.<br />
<br />
One pitfall is that, even though there is no visible locking, it is easy to create a deadlock if an Active Object's method posts (directly or indirectly) back to it's own channel, since channels have a fixed size once created. But this can be avoided as discussed above.<br />
<br />
One thing that is very easy to do in Go is accidentally access a <b><i>confined </i></b>variable from the wrong go-routine. In another language like C it would be easy (though not portable) to use an assertion to verify that code is running on the right thread. Unfortunately, Go does not provide any identifier for go-routines (for arguably good reasons), but this hinders attempts to ensure that the code behaves correctly. Luckily there are (deprecated) ways to determine an go-routine's "indentity" which I will explore and keep you informed.<br />
<br />
Also I have not explored how to wait for pending asynchronous operations to complete as I promised above. This post is long enough so we will look at that next time.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-30216102238135977622017-10-22T17:02:00.003+11:002017-11-02T10:02:11.726+11:00Improving Go Error HandlingLast time I mentioned that I had a way to improve error-handling in Go but I didn't get into the details. The idea is to use the compiler to eliminate all the boilerplate error-handling code but without the problems of full-blown templates.<br />
<br />
But first, let's try to understand why Go is designed as it is. An obvious, and major influence was experience with C so I will look at my experience with error-handling in C. (If you are not familiar with C then you may be inclined to skip the following section but please at least skim it.)<br />
<b><br /></b>
<span style="color: #0b5394; font-size: large;"><b>C Error-Handling</b></span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">C (and C++)...<br />are less forgiving</span></div>
<br />
Generally, error-handling in C is poor to non-existent. This has probably caused more aggravation for users than any other software deficiency of the last few decades. That's not to say that C programmers are of a lower standard (probably the contrary :), just that most of the commonly used software was written in C (and C++) and these languages are less forgiving if you do not know what you are doing.<br />
<br />
Here I share some of my experience with C, which is typical.<br />
<br />
I started programming in C in the early 1980's and one of the biggest tediums (tedia ?) was having to write masses of error-handling code, and making sure the code worked. As an example, consider this code to copy a file. (I know there are simpler ways to copy a file but this sort of code was like a lot of C code I was writing at the time.)<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
bool copy_file(const char *in_name, const char *out_name) {<br />
<span style="white-space: pre;"> </span>FILE *fin, *fout;<br />
<span style="white-space: pre;"> </span>const size_t BUF_SIZE = 1024;<br />
<span style="white-space: pre;"> </span>char * buf;<br />
<span style="white-space: pre;"> </span>size_t count;<br />
<span style="white-space: pre;"> </span><br />
<span style="white-space: pre;"> </span>if ((fin = fopen(in_name, "r")) == NULL)<br />
{<br />
<span style="white-space: pre;"> </span>return false;<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>if ((fout = fopen(out_name, "w")) == NULL)<br />
{<br />
<span style="white-space: pre;"> </span>fclose(fin);<br />
<span style="white-space: pre;"> </span>return false;<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>if ((buf = malloc(BUF_SIZE)) == NULL)<br />
{<br />
<span style="white-space: pre;"> </span>fclose(fin);<br />
<span style="white-space: pre;"> </span>fclose(fout);<br />
<span style="white-space: pre;"> </span>return false;<br />
<span style="white-space: pre;"> </span>}<br />
<br />
<span style="white-space: pre;"> </span>for (;;)<br />
<span style="white-space: pre;"> </span>{<br />
<span style="white-space: pre;"> </span>if ((count = fread(buf, 1, BUF_SIZE, fin)) < BUF_SIZE)<br />
<span style="white-space: pre;"> </span>{ // WARNING: see below<br />
<span style="white-space: pre;"> </span>if (feof(fin))<br />
<span style="white-space: pre;"> </span>break;<br />
<br />
<span style="white-space: pre;"> </span>fclose(fin);<br />
<span style="white-space: pre;"> </span>fclose(fout);<br />
<span style="white-space: pre;"> </span>free(buf);<br />
<br />
<span style="white-space: pre;"> </span>return false;<br />
<span style="white-space: pre;"> </span>}<br />
<br />
<span style="white-space: pre;"> </span>if (fwrite(buf, 1, count, fout) < count)<br />
{<br />
<span style="white-space: pre;"> f</span>close(fin);<br />
<span style="white-space: pre;"> </span>fclose(fout);<br />
<span style="white-space: pre;"> </span>free(buf);<br />
<span style="white-space: pre;"> </span>return false;<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>}<br />
<br />
<span style="white-space: pre;"> </span>fclose(fin);<br />
<span style="white-space: pre;"> </span>fclose(fout);<br />
<span style="white-space: pre;"> </span>free(buf);<br />
<br />
<span style="white-space: pre;"> </span>return true;<br />
}</div>
<div style="text-align: center;">
<b>Listing 1. C function to copy a file.</b></div>
<div style="text-align: center;">
<br /></div>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
“most C<br />error-handling code<br />is never tested”</span></div>
<br />
An obvious problem with <b>Listing 1</b> is that the large amount of error-handling tends to obscure the essence of the code. (Compare it with the same code without error-handling, in <b>Listing 3</b> below.) This sort of code is hard to write, hard to read and hard to modify. Further, it is difficult to verify that error-handling code is correct; in fact most C error-handling code is never tested and causes all sorts of chaos in the field when the actual errors do occur.<br />
<br />
<b><span style="color: #990000;">WARNING:</span></b> I should point out that <b>Listing 1</b> (and <b>Listing 2</b>), despite attempts at thorough error-handling has at least two problems. Can you spot them? Furthermore, production code should have more informative error handling - such as trying to diagnose, and inform the user why different errors occurred. For example, if the input file could not be opened was that because it did not exist, was not accessible or some other reason?<br />
<br />
Part of the complexity of <b>Listing 1</b> is due to all the <span style="color: #b45f06;">fclose/free/return</span> statements in the error-handling which are repetitive and error-prone (remember<span style="color: blue;"> <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a></span>). It would be quite easy to forget a call to <span style="color: #b45f06;">free()</span> and cause a memory leak. In fact the code I would typically write (if the coding standards in effect allowed use of <span style="color: #b45f06;">goto </span>:) would be more like this:<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
bool copy_file(const char *in_name, const char *out_name)<br />
{<br />
<span style="white-space: pre;"> </span>bool retval = false;<br />
<span style="white-space: pre;"> </span>FILE *fin = NULL, *fout = NULL;<br />
<span style="white-space: pre;"> </span>const size_t BUF_SIZE = 1024;<br />
char * buf = NULL;<br />
<span style="white-space: pre;"> </span>size_t count;<br />
<span style="white-space: pre;"> </span><br />
<span style="white-space: pre;"> </span>if ((fin = fopen(in_name, "r")) == NULL)<br />
<span style="white-space: pre;"> </span>goto handle_error;<br />
<span style="white-space: pre;"> </span>if ((fout = fopen(out_name, "w")) == NULL)<br />
<span style="white-space: pre;"> </span>goto handle_error;<br />
<span style="white-space: pre;"> </span>if ((buf = malloc(BUF_SIZE)) == NULL)<br />
<span style="white-space: pre;"> </span>goto handle_error;<br />
<br />
<span style="white-space: pre;"> </span>for (;;)<br />
<span style="white-space: pre;"> </span>{<br />
<span style="white-space: pre;"> </span>if ((count = fread(buf, 1, BUF_SIZE, fin)) < BUF_SIZE)<br />
<span style="white-space: pre;"> </span>{<br />
<span style="white-space: pre;"> </span>if (feof(fin))<br />
<span style="white-space: pre;"> </span>break;<br />
<span style="white-space: pre;"> </span>else<br />
<span style="white-space: pre;"> </span>goto handle_error;<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>if (fwrite(buf, 1, count, fout) < count)<br />
<span style="white-space: pre;"> </span>goto handle_error;<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>retval = true; // indicate success<br />
<br />
handle_error:<br />
<span style="white-space: pre;"> </span>if (fin != NULL)<span style="white-space: pre;"> </span>fclose(fin);<br />
<span style="white-space: pre;"> </span>if (fout != NULL)<span style="white-space: pre;"> </span>fclose(fout);<br />
<span style="white-space: pre;"> </span>if (buf != NULL)<span style="white-space: pre;"> </span>free(buf);<br />
<br />
return retval;<br />
}</div>
<div style="text-align: center;">
<b>Listing 2. Using goto to avoid repeated code.</b></div>
<div style="text-align: center;">
<br /></div>
Note that the Go language neatly addresses this problem with the <span style="color: #b45f06;">defer </span>statement as I mention later.<br />
<br />
Now look at the same function (<b>Listing 3</b>) without any error-handling code.<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
void copy_file(const char *in_name, const char *out_name)<br />
{<br />
<span style="white-space: pre;"> </span>FILE *fin = fopen(in_name, "r");<br />
<span style="white-space: pre;"> </span>FILE *fout = fopen(out_name, "w");<br />
<span style="white-space: pre;"> </span>const size_t BUF_SIZE = 1024;<br />
<span style="white-space: pre;"> </span>char *buf = malloc(BUF_SIZE);<br />
<span style="white-space: pre;"> </span>size_t count;<br />
<div>
<br /></div>
<span style="white-space: pre;"> </span>while ((count = fread(buf, 1, BUF_SIZE, fin)) > 0)<br />
<span style="white-space: pre;"> </span>fwrite(buf, 1, count, fout);<br />
<br />
<span style="white-space: pre;"> </span>free(buf);<br />
<span style="white-space: pre;"> </span>fclose(fout);<br />
<span style="white-space: pre;"> </span>fclose(fin);<br />
}</div>
<div style="text-align: center;">
<b>Listing 3. No error handling.</b></div>
<br />
This is plainly much simpler than the previous versions (and fixes the major bug). This is why many examples you see in textbooks omit the error-handling code to make it easier to understand.<br />
<br />
Unfortunately, a lot of production code is actually written like this! Moreover, even more (95% or more) has inadequate error-handling to some extent. Why is that?<br />
<br />
<ol>
<li>Blind following of example code from textbooks, as I just mentioned.</li>
<li>Lack of awareness that special values indicate errors, due to C's use of "in-band" signalling. I discuss how Go addresses this below.</li>
<li>Lack of awareness that some functions even return errors. For example, in <b>Listing 1</b>, the final <span style="color: #b45f06;">fclose(fout)</span> may return an error. (If buffered data can't be written to disk for some reason then <span style="color: #b45f06;">fclose()</span> will return an error.). Unfortunately, Go does not really address this problem.</li>
<li>The attitude (laziness?) of many C programmers. For example, many security threats have been caused by buffer overflow problems. Most C programmers are aware of the dangers of <span style="color: #b45f06;">strcpy()</span> but neglect using safer functions like <span style="color: #b45f06;">strncpy()</span>.</li>
<li>Poor reasoning. Sometimes you can ignore errors but often there may be subtleties of which you are unaware. For example, I have seen a lot of software that assumes you can write a file in current directory which is not always true</li>
<li>Code changes made without full understanding of the existing code.</li>
<li>Finally, occasionally, despite the best of intentions, errors are ignored by accident or oversight.</li>
</ol>
<br />
<b style="color: #0b5394; font-size: x-large;">How Go Improves on C</b><br />
<br />
Go has several facilities, such as the <span style="color: #b45f06;">error </span>type and multiple return values, that make error-handling simpler and safer than in C. (To be honest the standard C library's error-handling strategy, especially use of the global <span style="color: #b45f06;">errno</span> variable, could not be much worse.)<br />
<br />
<b><span style="color: #0b5394;">The error type</span></b><br />
<br />
Go eschews the common C error-handling pattern of "in-band signalling". That is, in C, when a function returns a value of a certain type it reserves a special value of that type to indicate a failure. When returning an integer, -1 is often used, or when returning a pointer, NULL is used. You can see this above in the calls to fopen() and malloc() which can return NULL pointers. A different example in the above code is fwrite(), which indicates an error by returning a written count less than the requested count.<br />
<br />
The are a few problems with in-band signaling:<br />
<br />
<ol>
<li>sometimes there is no spare value that can be used as the error value</li>
<li>you often want to return more information than just that something went wrong</li>
<li>it is easy to ignore the error return value and continue blithely</li>
<li>it may not even occur to the uninitiated that there is a special error return value</li>
</ol>
<br />
An example of the problem (1) can be seen in the code above - <span style="color: #b45f06;">fread()</span> will return zero on error to indicate that nothing could be read, but zero is <b><i>also </i></b>returned when you attempt to read at the end of file, which, in general, is <b>not </b>an error condition. One way this is handled in the C standard library is to check <span style="color: #b45f06;">errno </span>after the call (remembering to ensure it is zero before the call); in the case of <span style="color: #b45f06;">fread()</span> you need to do a further call to <span style="color: #b45f06;">ferror()</span> or<span style="color: #b45f06;"> feof()</span> to distinguish between an error and reading at EOF.<br />
<br />
(2) The C standard library uses the global <span style="color: #b45f06;">errno </span>variable to indicate more about the nature of the error. However, this is a poor strategy which has been discussed at length elsewhere.<br />
<br />
(3) and (4) are common in C and the cause of countless bugs.<br />
<br />
Go addresses these problems using the <span style="color: #b45f06;">error </span>type (and allowing functions to have multiple return values - see below). A function that may encounter an error returns a value of type <b><i><span style="color: #b45f06;">error</span></i></b> as well as its normal return value(s). If the error value returned is not nil then it indicates there was an error and the value can be further inspected to determine the exact nature of the problem.<br />
<br />
<b><span style="color: #0b5394;">Defer</span></b><br />
<br />
Although it is rarely mentioned when talking about error-handling in Go, understanding how to use the <b><i><span style="color: #b45f06;">defer </span></i></b>statement is critical.<br />
<br />
First using <span style="color: #b45f06;">defer </span>avoids lots of repetitive cleanup code (as seen in Listing 1 above). Moreover, I believe it greatly reduces the chances of accidentally forgetting cleanup code, and makes it easier to visually inspect code to check that cleanup is done. I have seen countless bugs in C code (and even created a few myself early on in my career) where some resource is allocated (eg file opened, resource handle allocated, mutex locked, etc) but then never released/closed/freed/unlocked causing a resource leak or worse.<br />
<br />
In C it is easy to forget to free something because the allocate and free functions are necessarily called at different places (classic example of the <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html"><span style="color: blue;">DIRE principle</span></a>). The problem is also often due to complex control flows or later code changes such as someone adding an early return from a function. Using <span style="color: #b45f06;">defer</span> in Go to free a resource immediately after it has been (successfully) allocated very neatly avoids these problems.<br />
<br />
Though the creators of Go may deny it, I think that <span style="color: #b45f06;">defer </span>is inspired by C++ destructors (which inspired <span style="color: #b45f06;">with</span>/<span style="color: #b45f06;">using</span> statements of other languages). As well as being called in normal return circumstances, destructors are called when an exception is thrown in C++ (during stack-unwinding); similarly <span style="color: #b45f06;">defer </span>statements are called when the code panics.<br />
<br />
The addition of <span style="color: #b45f06;">defer </span>to Go is especially useful for error-handling but there are a few pitfalls for the unwary:<br />
<br />
<span style="white-space: pre;"> </span>• Deferred functions are called at the end of the function not the enclosing block.<br />
(I expected behavior like C++ destructors which are called at the end of the block.)<br />
<span style="white-space: pre;"> </span>• Only defer freeing of a resource after checking that it was successfully allocated.<br />
<span style="white-space: pre;"> </span>• It’s common to see a deferred Close such as this:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">if file, err = os.Open(fileName); err != nil { return err }</span><br />
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>defer file.Close()</span><br />
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>…</span><br />
<span style="white-space: pre;"> </span><br />
The problem with this code is that it ignores the error-return value from Close(). Generally, it should be written like this:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">if file, err := os.Open(fileName); err != nil { return err }</span><br />
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>defer func() {</span><br />
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>if err = file.Close(); err != nil { return err }</span><br />
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>}</span><br />
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>…</span><br />
<br />
<b><span style="color: #0b5394;">Multiple Return Values</span></b><br />
<br />
A function in Go can return more than one value. I believe that a reason, probably the main reason, this was added to the language is to allow a function to return a value and an error condition without resorting to C's in-band signalling due to the problems discussed above (especially problem 3).<br />
<br />
Go forces you to explicitly say you are ignoring an error by using the <b><i>blank identifier</i></b> (a single underscore). For example:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">i, _ := strconv.Atoi(str)</span><br />
<br />
which converts a string into an integer. In this case if there is an error during the conversion then it is ignored, and<span style="color: #b45f06;"> i </span>retains the zero value. However, there are some problems with this system.<br />
<br />
First, even if you know an error will not occur, you cannot use the return value in an expression. I often want to use the return value of <span style="color: #b45f06;">strconv.Atoi()</span> in an expression knowing that the string represents a valid integer (or just being happy with a zero value, if not). It is tedious and error-prone to have to assign the return value to a temporary variable, which is why I usually wrap <span style="color: #b45f06;">Atoi()</span> in my own function which returns a single value.<br />
<br />
A bigger problem is that you can ignore easily ignore an error return value when you are not interested in any of the the returned values. It is all too common to see Go code that ignores the error return value of functions like <span style="color: #b45f06;">os.file.Close()</span>.<br />
<br />
For example, this generates a compile error:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">file := os.Open(fileName) </span> // compile error: multiple-value in single-value context<br />
<span style="white-space: pre;"> </span><br />
If you know the error will not occur, in a particular circumstance, then you can explicitly state that you do not want to use the error-return value like this:<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">when a function<br />only returns<br />an error in Go, it is<br />too easy to ignore it
</span></div>
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">file, _ := os.Open(fileName)</span><br />
<br />
However, you can call <span style="color: #b45f06;">Close()</span> like this:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">file.Close() </span> // compiles OK!!<br />
<br />
whereas having to do something like this would be preferable (if we know that <span style="color: #b45f06;">Close()</span> cannot return an error):<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">_ = file.Close()</span> // ignore error from Close()<br />
<br />
<br />
<b style="color: #0b5394;">A Go Example</b><br />
<br />
As an example, of how Go error-handling compares with C here is the same function as in <b>Listing 1</b> but written in Go (or a language like Go), using <span style="color: #b45f06;">defer </span>and multiple return values. Note that this is not real Go code as the standard file handling functions are different and Go has no need for anything like <span style="color: #b45f06;">malloc()</span>.<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func copy_file(in_name string, out_name string) error<br />
{<br />
<span style="white-space: pre;"> </span>var err error<br />
<span style="white-space: pre;"> </span>var fin, fout *file<br />
<span style="white-space: pre;"> </span>if fin, err = fopen(in_name, "r"); err != nil {<br />
<span style="white-space: pre;"> </span>return err<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>defer fclose(fin)<br />
<span style="white-space: pre;"> </span>if fout, err = fopen(out_name, "w"); err != nil {<br />
<span style="white-space: pre;"> </span>return err<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>defer fclose(fout)<br />
<span style="white-space: pre;"> </span><br />
<span style="white-space: pre;"> </span>var buf []byte<br />
<span style="white-space: pre;"> </span>if buf, err = malloc(1024); err != nil {<br />
<span style="white-space: pre;"> </span>return err<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>defer free(buf)<br />
<br />
<span style="white-space: pre;"> </span>for {<br />
<span style="white-space: pre;"> </span>if eof, err := fread(buf, fin); err != nil {<br />
<span style="white-space: pre;"> </span>return err<br />
<span style="white-space: pre;"> </span>}<br />
if eof {<br />
<span style="white-space: pre;"> </span>break<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>if err = fwrite(buf, fout); err != nil {<br />
<span style="white-space: pre;"> </span>return err<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>}<br />
<span style="white-space: pre;"> </span>return nil<br />
}</div>
<div style="text-align: center;">
<b>Listing 4. Error handling in a "GO" like language</b></div>
<br />
Comparing <b>Listing 4</b> with <b>Listing 1</b> you can see that there are some improvements, but it is still far from ideal when you compare it with <b>Listing 3</b>. You might argue that the only way to get anything like <b>Listing 3</b> is to have exceptions added to the language - I agree that exceptions have advantages, but they also have negatives - so we take a slight detour to consider why Go does not have exceptions.<br />
<br />
<span style="color: #0b5394; font-size: large;"><b>Exceptions</b></span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">exceptions<br />simply can't be<br />... ignored! </span></div>
There are two major advantages with exceptions, plus a disadvantage.<br />
<br />
<b><span style="color: #0b5394;">Advantages</span></b><br />
<br />
A. If you search on the Internet for the advantages of exceptions you find all sorts of things mentioned (eg the first hit at Google I get is to <a href="https://docs.oracle.com/javase/tutorial/essential/exceptions/advantages.html"><span style="color: blue;">the Java documentation on exceptions</span></a>). What they fail to mention is the most important one - exceptions simply can't be (accidentally or intentionally) ignored! This was the first thing that struck me when I first read of exceptions in<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 250px;">
<span style="font-size: x-small;">* Note that nowadays these sort of C bugs are <i>sometimes</i> detected in some way and the software terminated by the operating system but when I started using C on operating systems without hardware memory protection (eg MSDOS, AmigaDOS, etc) an ignored error could cause mayhem, eg:</span><span style="font-size: x-small;"> behave erratically, even corrupt its own data and save it to disk. It might also trash other running software, or bring down the OS!</span></div>
Stroustrup's <b><i>The C++ Programming Language, 2nd Edition</i></b> as I had spent many painful years tracking down bugs of this nature in C code* - if an error occurs you throw an exception and the program stops, unless steps are taken to catch it.<br />
<br />
B. Of course, the other major advantage of exceptions is reduced complexity (see <b>Listing 3</b>). The error-processing code does not obscure the "normal" control flow. This makes the software more understandable and even easier to get right. And of course, it relieves the tedium of writing lots of similar, uninteresting code.<br />
<br />
<b><span style="color: #0b5394;">Disadvantages</span></b><br />
<br />
From the above advantages you can see that exceptions are great to (A) ensure that errors are not ignored and (B) to make "normal" code easier to write and understand. In other words they are great when:<br />
<br />
A. exceptions are thrown and not caught (error causes program to terminate)<br />
B. exceptions are never thrown (no error encountered)<br />
<br />
The real problems occur when:<br />
<br />
C. exceptions are thrown and caught<br />
<br />
The reason is that exceptions are often thrown when you are not expecting it. At the point they are caught it is easy for the software to be left in an inconsistent state causing memory/resource leaks and even more serious bugs. In fact there are many examples of simple, seemingly innocuous, C++ code where an exception causes that most heinous of coding-crimes: undefined behavior.<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="font-size: x-small;">This is not too serious if exceptions are used properly and sparingly but the last decade has revealed a new problem - the gross overuse and misuse of exceptions for normal control flow as seen in a lot of Java code.
</span></div>
<span style="white-space: pre;">To elaborate, y</span>ou <b><i>can</i></b> write safe code using exceptions but it is hard. The trouble is you have to always be thinking about what exceptions could be thrown in addition to the actual problem that you are trying to solve. And the human brain is not good at multi-tasking.<br />
<br />
Furthermore, exceptions and concurrency do not mix well. (Eg: see the section on <span style="color: #0b5394;">Mismatch With Parallel Programming</span> in <a href="http://www.lighterra.com/papers/exceptionsharmful/"><span style="color: blue;">Exception Handling Considered Harmful</span></a>). Go makes writing concurrent code easy, so it seems better to avoid exceptions in the language.<br />
<br />
<b><span style="color: #0b5394;">Go</span></b><br />
<br />
So Go does not have exceptions due to their major problem (C above). Go attempts in other ways to obtain their benefits (A and B), but does does not do so effectively. My proposal is to enhance the Go compiler's support for error handling to obtain the benefits that exceptions give to A and B.<br />
<br />
<span style="color: #0b5394; font-size: large;"><b>The Proposal</b></span><br />
<br />
My proposal relies on the compiler generating some hidden code. (Alternatively, this could be done by some sort of preprocessing of Go code.)<br />
<br />
In summary, I propose these changes to Go:<br />
<br />
<ul>
<li>If a function is called which returns one or more values, the last of which is of type <span style="color: #b45f06;">error</span>, and</li>
<li>if that last returned (<span style="color: #b45f06;">error</span>) value of the function is not assigned or used AND</li>
<li>the calling function also has a (last) error-return value THEN</li>
<li>the compiler will automatically add code to check the error return value AND</li>
<li>if the called function returns an error then the calling function should return the same error</li>
</ul>
Returning tto our original example, <b>Listing 5</b> has the same copy function as <b>Listing 4</b> but with no error-handling, which is proposed to be implicitly added by the compiler.<br />
<br />
<div style="background-color: #e1e1e1; color: #b45f06; font-family: "courier new" , "courier" , monospace;">
func copy_file(in_name string, out_name string) error<br />
{<br />
<span style="white-space: pre;"> </span>fin := fopen(in_name, "r")<br />
<span style="white-space: pre;"> </span>defer fclose(fin)<br />
<span style="white-space: pre;"> </span>fout := fopen(out_name, "w")<br />
<span style="white-space: pre;"> </span>defer fclose(fout)<br />
<span style="white-space: pre;"> </span>buf := malloc(1024)<br />
<span style="white-space: pre;"> </span>defer free(buf)<br />
<br />
fmt.Println("Copying", in_name, "to", out_name)<br />
<span style="white-space: pre;"> </span>for fread(buf, fin) != eof {<br />
<span style="white-space: pre;"> </span>fwrite(buf, fout)<br />
<span style="white-space: pre;"> </span>}<br />
<br />
}</div>
<div style="text-align: center;">
<b>Listing 5 Copy function with implicit error-handling.</b></div>
<br />
the compiler would generate code equivalent to:<br />
<br />
<div style="background-color: #e1e1e1; font-family: "courier new", courier, monospace;">
<div style="color: #b45f06;">
func copy_file(in_name string, out_name string) error</div>
<div style="color: #b45f06;">
{</div>
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>fin</span><b><span style="color: red;">, err</span></b><span style="color: #b45f06;"> := fopen(in_name, "r")</span><br />
<span style="color: #b45f06; white-space: pre;"> </span><span style="color: red; font-weight: bold;">if (err != nil) {</span><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>return err</span></b><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>}</span></b><br />
<div style="color: #b45f06;">
<span style="white-space: pre;"> </span>defer fclose(fin)</div>
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>fout</span><b><span style="color: red;">, err</span></b><span style="color: #b45f06;"> := fopen(out_name, "w")</span><br />
<span style="color: #b45f06; white-space: pre;"> </span><span style="color: red; font-weight: bold;">if (err != nil) {</span><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>return err</span></b><br />
<b><span style="color: red;"> }</span></b><br />
<div>
<span style="color: #b45f06;"> defer </span><b><span style="color: red;">func() {</span></b><br />
<b><span style="color: red;"> err := </span></b><span style="color: #b45f06;">fclose(fout)</span><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>if (err != nil) {</span></b><br />
<span style="color: red;"><b><span style="white-space: pre;"> </span>return err</b></span><br />
<span style="color: red;"><b><span style="white-space: pre;"> </span>}</b></span><br />
<div>
</div>
<b><span style="color: red;"> }</span></b></div>
<span style="color: #b45f06;"><span style="white-space: pre;"> </span>buf</span><b><span style="color: red;">, err</span></b><span style="color: #b45f06;"> := malloc(1024)</span><br />
<span style="color: #b45f06; white-space: pre;"> </span><span style="color: red; font-weight: bold;">if (err != nil) {</span><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>return err</span></b><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>}</span></b><br />
<div style="color: #b45f06;">
defer free(buf)</div>
<div style="color: #b45f06;">
<span style="white-space: pre;"> </span></div>
<div style="color: #b45f06;">
<span style="color: red;"><b>_, err =</b></span><span style="color: red;"> </span>fmt.Println("Copying", in_name, "to", out_name)<br />
<div style="color: black;">
<span style="color: #b45f06;"> </span><span style="color: red;"><b>if err != nil {</b></span></div>
<div style="color: black;">
<span style="color: red;"><b><span style="white-space: pre;"> </span>return err</b></span></div>
<div style="color: black;">
<span style="color: red;"><b><span style="white-space: pre;"> </span>}</b></span></div>
<span style="white-space: pre;"> </span>for {</div>
<span style="color: #b45f06; white-space: pre;"> </span><b><span style="color: red;">tmp, err := </span></b><span style="color: #b45f06;">fread(buf, fin)</span><br />
<span style="color: #b45f06; white-space: pre;"> </span><b><span style="color: red;">if (err != nil) {</span></b><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>return err</span></b><br />
<b><span style="color: red;"><span style="white-space: pre;"> </span>}</span></b><br />
<span style="color: #b45f06;"> </span><b><span style="color: red;">if tmp == eof</span></b><span style="color: #b45f06;"> {</span><br />
<div style="color: #b45f06;">
break;</div>
<div style="color: #b45f06;">
}</div>
<div>
<span style="white-space: pre;"><span style="color: #b45f06;"> </span><span style="color: red;"><b>err =</b></span></span><span style="color: red;"> </span><span style="color: #b45f06;">fwrite(buf, fout)</span><br />
<span style="color: #b45f06;"> </span><span style="color: red;"><b>if err != nil {</b></span><br />
<span style="color: red;"><b><span style="white-space: pre;"> </span>return err</b></span><br />
<span style="color: red;"><b><span style="white-space: pre;"> </span>}</b></span><br />
<div style="color: #b45f06;">
<span style="white-space: pre;"> </span>}</div>
<div style="color: #b45f06;">
}</div>
</div>
</div>
<div style="text-align: center;">
<b>Listing 6 Same function showing compiler-generated error-handling.</b></div>
<br />
In this way errors can be propagated up the call stack without the need for explicit error-handling code at each level. Even accidentally forgetting to check the error return value of a function like <span style="color: #b45f06;">close()</span> will automatically be handled.<br />
<br />
Of course, at any level you can override the compiler generated code, if it's error-handling is insufficient. This is done by simply using the error return value.<br />
<br />
Or, if you know the error condition won't occur then you can explicitly assign the error to the <i>blank identifier</i> to ignore it.<br />
<br />
A further advantage is that functions which return a result and an error can be used in expressions like this:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">calc(strconv.Atoi(str))</span><br />
<div>
<span style="color: #b45f06;"><br /></span></div>
instead of:<br />
<br />
<span style="white-space: pre;"> </span><span style="color: #b45f06;">tmp, _ := strconv.Atoi(str)<br /><span style="color: black; white-space: pre;"> </span><span style="color: #b45f06;">calc(tmp)</span></span><br />
<span style="color: #b45f06;"><br /></span>
which avoids the use of error-prone temporaries and has the added advantage that if <span style="color: #b45f06;">Atoi()</span> unexpectedly does get an error that it will be detected and returned.<br />
<br />
<b><span style="color: #0b5394;">Auxiliary Proposal</span></b><br />
<br />
In addition, I have a related, but independent, proposal.<br />
<div>
<ul>
<li>If a function just returns an <span style="color: #b45f06;">error</span> then you must use it (or assign to the blank identifier)</li>
</ul>
</div>
<div>
That is, this code should generate a compile-time error:</div>
<div>
<br /></div>
<div>
<span style="white-space: pre;"> </span><span style="color: #b45f06;">file.Close() </span> // compile error: error return cannot be ignored</div>
<div>
<br /></div>
<div>
To explicitly ignore the error you must do this:</div>
<div>
<br /></div>
<div>
<div>
<span style="white-space: pre;"> </span><span style="color: #b45f06;">_ = file.Close() </span> // ignore error return value from Close</div>
</div>
<div>
<br />
Combined with the above main proposal this makes code much safer. In fact a lot of existing code that ignores the return value of <span style="color: #b45f06;">Close() </span>will now be safer without any code changes! Of course, without my main proposal this proposal would mean modifying a lot of existing code, such as most uses of <span style="color: #b45f06;">fmt.Printf()</span>.</div>
<div>
<br /></div>
<span style="color: #0b5394; font-size: large;"><b>Summary</b></span><br />
<br />
Two of the biggest problems I found in decades of programming in C were:<br />
<br />
<span style="white-space: pre;"> </span>1. code that ignored error return values, often with severe consequences<br />
<span style="white-space: pre;"> </span>2. having to write lots of boilerplate error-handling code<br />
<br />
Exception handling (as first implemented in C++) was a great boon in addressing both of these problems. However, exception handling introduced problems of it's own (as mentioned above) and the creators of Go chose not to add exception handling to the language, which I endorse.<br />
<br />
Unfortunately, Go's approach to error-handling is not that much better than C. It attempts to address problem 1 but does not do so convincingly. For example, it is easy to accidentally ignore an error-return value from a function that only returns one value.<br />
<br />
Problem 2 has been alleviated somewhat by the introduction of the <span style="color: #b45f06;"><b>defer </b></span>statement, but it is still tedious and error-prone - the sort of thing that a computer can do. Many people, including the Go creators, have debated this subject at length but their proposed strategies can be as tedious as the problem and are not generally applicable (at least until generics are added to Go. :).<br />
<br />
My proposal addresses both the above problems without using exceptions. It relieves the tedium of writing a lot of very similar code, and makes the code easier to scan, and hence less likely to have bugs.<br />
<br />
<b>The benefits are obvious from comparing Listing 4 and Listing 5 above.</b><br />
<br />
It also has the added advantage that functions that return two values, like<span style="color: #b45f06;"> <b>strconv.Atoi</b>()</span>, can be used in expressions when the error return value is not needed. Again this can make the code simpler, by avoiding error-prone temporaries, and easier to read.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com2tag:blogger.com,1999:blog-7237530825191390698.post-32297093912838472392017-08-20T20:48:00.003+10:002017-08-20T20:48:40.613+10:00The Essence of GoThe Go programming language - what do you know about it? I was looking for my next favorite language a couple of years ago. I tried and rejected Go based on a fair bit of research. However, I have been working on a project for the last few months using Go and I must admit my initial impressions were wrong. Here I hope to describe what using Go is really like for anyone thinking of trying it so they don't jump to the same erroneous conclusions that I did.
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 180px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">“… what using Go is really like …”</span></div>
<br />
Last year I mentioned here another new language, Rust, that I am very excited about (and which I hope to talk more about soon). Go is similar to Rust in many ways but Go is <i>not</i> a low-level language like Rust (despite what Google and others say). I would classify Go as a medium-level language on a par with C#. For one thing a language can't be low-level unless it allows control of memory allocations, but Go (like C#, Java and many interpreted languages) uses GC - ie, memory management is handled by the run-time using a garbage collected heap (I might talk more about that later).<br />
<br />
Initially I decided to steer clear of Go, for several reasons but mainly due to its lack of support for templates (generics) - which BTW Rust does have. But now that I have used Go I think one particular aspect is brilliant - it makes programming simple (in a myriad of ways), even more so than C# (which I talked about last time). And if you have read much of my blog you may have noticed my love of simplicity. I believe complexity is at the root of all problems in software development (see my very first post <a href="https://devmethodologies.blogspot.com.au/2011/10/handling-software-design-complexity.html"><span style="color: blue;">Handling Software Complexity</span></a>).<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Influences</b></span><br />
<br />
Whenever I try a new language I quickly get a feel for its style - what the designer(s) think is important (performance, flexibility, safety, etc). I can also usually pick what other languages influenced it. But Go's style and influences confusing.
<br />
<div style="float: left; line-height: 32px; padding: 16px; text-align: center; width: 150px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">Go's style and influences are confusing</span></div>
<br />
First, it's overriding premise seems to be to keep things simple (and most of the time it does that very well), but the motivation for this is a mystery. The initial impression I got was that it was that everything was done "on the cheap" - that is, the Go creators just found it too hard, or too time-consuming, to think about adding exception handling or templates or whatever. This is clearly wrong when you consider some of the other features that are present. I next formed the opinion that it was based on an intense dislike of C++, so anything that Bjarne Stroustrup invented was simply rejected out of hand. My current (final?) impression is that the creators of Go consider the average programmer to be lazy and incompetent so everything is kept as simple and safe as possible (though sometimes making things safer detracts from simplicity as we will see).
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 220px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">“ …making things safer detracts from simplicity…”</span></div>
<br />
Go's influences are many but as a generalization I would say that Go is a bit like a simplified C#, with all the C++ derived stuff removed, plus some additional features that support concurrency. For example, it has features similar or the same as these from C#: GC (memory management), lambdas (called closures in Go), metadata, reflection, interfaces, zero initialization, immutable strings, partial classes, extension methods, implicit typing (var), etc. And like C#, Go also tries to avoid lots of the problem areas of C/C++ such as expressions with undefined behavior.<br />
<br />
<div style="float: left; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">Go is like C# with the C++ stuff removed</span></div>
On the other hand almost all the things that C# inherited from C++ Go completely discards - like generics, exception handling, operator overloading, implicit conversions, and even classes and inheritance.<br />
<br />
However, there are a few more things to Go that seem to be new or come from elsewhere. One of the most interesting is its support for concurrency, including channels which I first encountered in Occam about 25 years ago. And, of course, like all popular modern languages Go is heavily influenced by C and C++ (though in the case of C++ the influence is in the form of avoidance). Let's look at these influences just a bit more.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Safer C</span><br />
<br />
Go has strong links to C, ostensibly because Google wanted a modern alternative to C. I think a big reason is that one of the Go architects is Ken Thompson who (along with Dennis Ritchie) created the C language (and the Unix operating system) and even precursors to C in the 1960's.<br />
<br />
The syntax of Go is obviously derived from C, but there are many "improvements" to avoid problems that many beginners in C encounter. A good example is that there is no automatic "fall through" between cases in a switch statement which is a perennial source of bugs in C. On the other hand side-effects in expressions have been removed (eg, no assignment chaining etc) which is bad (see below).<br />
<br />
Most of the problems with using pointers that C is notorious for have been eliminated by disallowing pointer arithmetic and by automatic memory handling using the garbage-collected heap.<br />
<br />
Another common problem for beginners in C is due to uninitialized variables which can lead to bugs which are almost impossible to track down due to unreproducibility. Go's solution is the "shotgun" approach where everything is guaranteed to be initialized to a "zero" value. This is good for reproducibility but introduces its own problems as I discussed in <a href="http://devmethodologies.blogspot.com.au/2012/02/shotgun-initialization.html"><span style="color: blue;">Shotgun Initialization</span></a>.<br />
<br />
Finally, I should mention that Go tries to address perhaps the worst problem of most C code (yes worse than the above problems!). This is the problem that there is an enormous amount of C code that ignores error conditions or does not handle them correctly. Go has a more systematic approach to error handling but, in all honesty, it is only marginally better than the C approach. Now I am not saying that Go should have exceptions and I understand and agree with the decision not to have them (even though it effectively does have them in the form of panic/recover). All I am saying is that Go should do something about relieving the tedium and complexity of C-like error-handling and in fact I have a proposal to do just that - more on this later.<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">“Go error-handling is <br />only marginally better than C”</span></div>
<br />
In summary, the designers of Go have honored the age-old tradition of finding ways to improve on C. Some of the improvements are actually useful but some are just denigrating to competent programmers.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Occam</span><br />
<br />
Go is the first language I have encountered since Occam to use the brilliant idea of communication between concurrent processes using "channels". Apparently channels are heavily used in Erlang and other languages that I have not had the fortune to use. However, at one time (more than 25 years ago) I was very interested in the Inmos Transputer which you can read more about <a href="https://en.wikipedia.org/wiki/Transputer"><span style="color: blue;">here</span></a> but basically it was designed to allow multiple CPUs to be hooked together easily.<br />
<br />
Occam had other features which I thought were going to be very important such as the ability to say whether instructions could be parallelized or must be run sequentially.<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 256px;">
<span style="font-size: x-small;">I became interested in the Transputer as it was a little like my own (even more way-out) idea for a bit-oriented processor. At the time single chip CPUs were 8 or 16 bit.<br /><br />My thinking was that there large benefits in moving to single-bit processors which read from memory, and other CPUs serially - ie, one bit at a time. Each CPU would be like a neuron. They could be hooked together to make something more powerful.<br /><br />The industry successfully advanced in the opposite direction and soon 32-bit processors (and now 64-bit CPUs) are the norm. I'm not sure that this was the right direction. Maybe one day single-bit computers will find a place.</span></div>
<br />
At the time I thought the software industry needed to embrace multi-threading (or multi-tasking as it was called then). At the time even the major operating systems from Microsoft and Apple did not support multi-tasking (using a kludge called "co-operative multi-tasking). Unfortunately, it was another decade before mainstream operating systems and languages were supporting multi-threading.<br />
<br />
It's a shame that the Transputer and Occam never became popular. I think they were ahead of their time.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Not C++</span><br />
<br />
As I said above I think one of the main influences on Go is that it avoids anything invented by C++. Here is a list and my opinion of whether that is good or bad.<br />
<ol>
<li>No support for <b>inheritance</b>, ie. no vtables etc, as used in compiled OO languages. This is <i>not</i> a bad thing, since inheritance is over-used, badly used and even when used well there are simpler alternatives. When required, Go has mixins (struct embedding) and interfaces, which are perfectly adequate.</li>
<li>No <b>templates</b>. Templates (which made possible the amazing STL) are the thing I like most about C++. This <i>is</i> a bad thing.</li>
<li>No <b>exceptions</b>. I appreciate the argument for no exceptions, but I wish the alternative provided by Go was better. (Rust has no exceptions, but handles errors better using algebraic data types.) Go tries to improve on C's error-handling (which is very bad) but it is almost as easy to ignore errors in Go as C and the tedium of creating masses of error-handling code is back. Not being one to simply criticize, I propose how to improve Go's error-handling below.</li>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">“I propose how to<br />improve Go error-handling”</span></div>
<li>No <b>namespaces</b>. Go has a similar concept of packages (sort of like a combination of assembly and namespace of C#). Unfortunately, packages can't be nested, which is limiting.</li>
<li><b>Const</b> was one of the simplest and most brilliant inventions of C++. I can't believe Go (and other modern languages) even consider leaving it out.</li>
<li>No public/private/protected keywords. Go has a system where capitalized variable names are public, but a lower-case first letter means it is private to the package (a bit like internal in C#). This is simple but I am undecided whether it is sufficient.</li>
<li>No user-defined <b>operator-overloading</b>. (Of course, like most languages there is operator-overloading for built-in types.) I don't really miss this.</li>
<li>No <b>function overloading</b> (except you can overload methods with different receiver types - otherwise interfaces would not work). I miss this ability but I guess it is not essential.</li>
<li>No <b>optional parameters</b>. I understand the problems of optional parameters, but they are rarely seen in practice. Not a biggy but the alternatives in Go are all error-prone and/or tedious to implement.</li>
<li>Go eschews the C++ philosophy that you should be able to create user-defined types that are as simple and flexible to use as the built-in types (eg see 7 above). Some people hate this about Go, but personally I am not that fussed as long as it gives me everything I need to do the job simply and effectively (which it usually does)</li>
<li>There is nothing as flexible and useful as the <b>STL</b>. This is bad.</li>
<li>One thing Go does use that comes from C++ is the // end of line comments. (Maybe the Go designers were not aware where that came from :)</li>
</ol>
In summary, leaving all the C++ stuff out greatly simplifies things (and I don't like a lot of the complexity of C++ either, as you may have guessed from some of my previous posts). However, I think the designers of Go may have thrown out the baby with the bath-water. In particular, I think templates (generics) and const are essential for any modern language.<br />
<br />
<b style="color: #3d85c6; font-size: x-large;">Simplicity</b><br />
<br />
Leaving out lots of features found in C++ and other languages makes Go programming simpler, but there are a lot of other niceties. Here is a list of all the things I like about Go.<br />
<ul>
<li><b><span style="color: #3d85c6;">Simple Builds</span></b> Probably the best thing about Go is how easy it is to build a project. In the past (on C projects) I have spent hours or even days trying to sort out problems with header file inclusion, linking or even run-time problems due to incompatible struct member alignment, not to mention<span style="color: blue;"> <a href="https://en.wikipedia.org/wiki/DLL_Hell">DLL Hell</a></span>. C++ improved on C by using name-mangling so the linker could catch many mistakes. Then C# (actually .Net) further alleviated build problems using metadata to completely describe how to attach to an assembly. Go takes this a step further and makes building software quick, painless and trouble-free.<b><br /></b></li>
<li><span style="color: #3d85c6;"><b>Integration</b></span> I have always found integrating an open-source library into my own project or even downloading and building a complete application time-consuming and frustrating. (For example, I have spent weeks trying to streamline the build process for my own project which uses several open-sources libraries - see <a href="https://github.com/AndrewWPhillips/HexEdit">HexEdit</a>.) In Go you simply use <b><i>go get</i></b> which finds and installs an open-source project and dependent projects so you can start using it straight away.</li>
<li><span style="color: #3d85c6;"><b>Compilation Speed</b></span> Go's build speed is amazing (mainly because the metadata for a package also stores all info about its dependent packages). I never used to think build speed was that important since you can take a break while the project is building. However, Go's almost instant builds makes things possible like the IDE checking your code for all errors (not just syntax errors) as you type, which is great.</li>
<li><b><span style="color: #3d85c6;">Type Safety</span></b> Because of the quick build speed developing with Go has the feel of using an interpreted language like Python. The problem with an interpreted language, though, is that a lot of errors aren't found until you run the program. Go on the other hand catches many errors at compile-time resulting in greater confidence that the code will run without error.</li>
<li><b><span style="color: #3d85c6;">Memory Management</span></b> Another huge tedium in many C programs is keeping track of heap memory and knowing who has to free it. And, if you get it wrong then you can have memory-leaks, double-frees and even nastier problems such as overwriting memory that is used for something else. Go avoids all of this by using a garbage collected heap while somehow avoiding any major performance hit. (My guess is it makes typical code about 30% slower, but at least it does not suffer from the large pauses that you see in multi-generational GC systems like C#). Rust, BTW, does not use GC, having an even better system that allows it to track and free used memory (or anything) automatically.</li>
<li><b><span style="color: #3d85c6;">OO</span></b> One of the best things about Go is its support for inheritance - there is none. I have spent decades trying to remember all the intricacies of C++ inheritance (and still forget things). Go is simple but has all you need in interfaces and mixins for most modern design patterns. There are some inheritance-based design patterns, such as the template pattern (see <a href="https://en.wikipedia.org/wiki/Template_method_pattern"><span style="color: blue;">Template Method Pattern</span></a>) which you would not implement in Go but in my opinion these are not good design patterns anyway.</li>
<li><b><span style="color: #3d85c6;">Concurrency</span></b> Many forms of concurrent programming are greatly simplified with the use of go-routines and channels, as I mentioned above.</li>
<li><b><span style="color: #3d85c6;">Closures</span></b> Some narrow-minded people claim that Go is not a modern language because it does not support any modern features like OO, generics and exceptions. This claim is discredited by its support for closures - something that did not even make it into C++ (as lambdas) until 2011. Though not as powerful (ie complicated) as lambdas in C++ they are simple and adequate for use with modern design patterns.</li>
<li><b><span style="color: #3d85c6;">Interfaces</span></b> Interfaces in Go are simpler and more flexible than other languages like Java and C# or the abstract base type of C++, since a type does not need to explicitly state that it implements an interface. People have mentioned complications with this system but in reality it works fine.</li>
<li><b><span style="color: #3d85c6;">Information Hiding</span></b> Go has a very simple system of denoting that a value is visible outside a package. If the identifier starts with a capital letter it is visible (called public in C++, C# etc), otherwise it is only usable inside the package (like internal in C#). Once again this is simple and effective. I have at times found this cumbersome when I want to hide parts of a package from other parts but I think a refinement that avoids this problem (and may be a better design in general) is to have small "internal" packages.</li>
<li><b><span style="color: #3d85c6;">Unit Tests</span></b> If you have read my blog you know that I love Unit Tests (see my posts from the end of 2013 and the start of 2014 such as <a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-whats-so-good-about-them.html"><span style="color: blue;">this</span></a>). I have tried different C# and C++ Unit Test frameworks and they can be tedious to understand, set-up and start using. In contrast, the unit test framework that comes with Go and is very easy to use. Note that the name "automated package tests" is preferred (I'm not fond of the term <b><i>unit test</i></b> either but it seems to be the term commonly used).</li>
<li><b><span style="color: #3d85c6;">Code Coverage</span></b> A very good thing to do is run code coverage tests on your <b><i>Unit Tests</i></b> to ensure that all or most of the code is tested. (Note that even 100% code coverage does not mean you have no bugs but it is a good indicator of how thorough your tests are.) Despite the benefits, I rarely ran code coverage checks until I started using Go simply because it was too hard. Go makes it easy to get simple code coverage statistics and not that much harder to do even more sophisticated analysis.</li>
<li><b><span style="color: #3d85c6;">Benchmarks</span></b> I use benchmarks a lot, for example to check the performance of a function or compare algorithms and have created my own C++ classes for this purpose. Go comes with a simple, flexible, and effective benchmarking system which can even be used for timing concurrent algorithms.</li>
<li><b><span style="color: #3d85c6;">Profiling </span></b>Profiling allows you to find performance bottlenecks in your software. Go has built-in support for profiling too, though I have not yet needed to try it.</li>
<li><b><span style="color: #3d85c6;">Identifiers</span></b> Finally, though this is more the culture of Go than the language per se, but I really like the emphasis on short, simple (but meaningful) identifiers instead of some of the monstrosities you see in Java and other languages. See <a href="http://devmethodologies.blogspot.com.au/2012/04/long-identifiers-make-code-unreadable.html"><span style="color: blue;">Long Identifiers Make Code Unreadable</span></a> for more info.</li>
</ul>
<b style="color: #3d85c6; font-size: x-large;">Complexity</b><br />
<br />
Despite its emphasis on simplicity Go does not always succeed. Many features seem to be designed to make things simpler for "beginners" but end up making things more complex for those who know what they are doing. I am all in favor of making things safer but it should not get in the way of competent developers. Here are a few examples:<br />
<ul>
<li><b><span style="color: #3d85c6;">Side effects</span></b> Expressions in Go are based on C expressions but (most) side effects have been removed (ie the operators ++, --, =, +=, etc). I guess this is to avoid expressions with undefined behavior that novices often write in C (like <span style="color: #b45f06;">a[i] = i++</span>). The consequence is that things that are easily and sensibly expressed in C/C++ cannot be in Go, often requiring use of temporary variables and more lines of code. This makes code more complex and harder to read. [Note that function calls can still cause side effects in Go expressions resulting in undefined behavior - eg, see <a href="https://github.com/golang/go/issues/15905"><span style="color: blue;">this</span></a>.]</li>
<li><b><span style="color: #3d85c6;">Operators</span></b> Similarly, the ternary (?:) and comma operators are not supported (plus maybe others I have not noticed yet). This cuts down the large and confusing precedence table of C, but makes it painful to produce concise and easily scanned code.</li>
<li><b><span style="color: #3d85c6;">Map Iteration Order</span></b> If you iterate over the elements of a map in Go the order of elements is deliberately unpredictable to prevent someone depending on the order. When I first read of this I thought it was an interesting idea, but what idiot would depend on the order of elements from a hash table?!! I didn't really foresee any problems with it until I came to debug a problem with data from a map. In that circumstance it is an absolute pain to restart a debug session and find your way back to the same point.</li>
<li><b><span style="color: #3d85c6;">Unused Variables </span></b>One of the biggest annoyances is that the Go compiler won't under any circumstances allow the code to build if there are unused variables or unused imports. Now this is great for finished code but is a complete pain in the q*** when you are writing, testing or debugging. The justification for using errors and not just a warning is (from the Go website) "if it's worth complaining about, it's worth fixing in the code". I agree entirely that it's worth fixing just NOT RIGHT NOW. Perhaps this problem can be addressed with a good IDE and better debuggers but it needs urgent addressing. Here are some examples to demonstrate the problem:</li>
<ul>
<li>I accidentally paste some code into the wrong source file and the IDE (Gogland in this case) "kindly" adds a dozen imports at the top of the file. After I delete accident, the code no longer builds and I have to manually go and delete the bogus imports.</li>
<li>I add an import I know I will need and save the file and the IDE (VSCode in this case) "kindly" deletes the unused imports for me - annoying. Later on when I use the imported function the IDE can't seem to determine how to re-add the import and I have try to remember where it was and add it again manually.</li>
<li>I declare a variable and the IDE draws a red squiggle under it to indicate an error. So I click on it to find it's just trying to tell me it is unused. Of course, it's unused I just declared it!</li>
<li>I want to see the value of an expression while testing so I assign to a temp variable so I can inspect it in the debugger but then the compiler won't even build the code.</li>
</ul>
<li><b><span style="color: #3d85c6;">Shadowing</span></b> A source of bugs (in C/C++, Pascal/Delphi, Java, Python, Go and other languages that allow it) is shadowing, where an identifier in an inner scope hides the same name in an outer scope. For example, you might add some code with a new variable which changes the behavior of code at the same level which uses an outer variable of the same name. In decades of programming in the above languages I have encountered bugs caused by this rarely but Go seems to make it much more likely because of the special if statement and how easy it is to use ":=" instead of "=". Go would be safer if it disallowed shadowing, like in C#, or the compiler could at least warn about it (as many C compilers do).</li>
<li><b><span style="color: #3d85c6;">Assertions</span></b> One of the first things I discovered about Go is that it doesn't have assertions. (There is even a dubious explanation of this in the official Go FAQ.) I love assertions as they have saved me (literally) years of debugging time but I admit with the advent of exceptions and unit tests they have less use. Luckily, Go actually does have them under the name of panic.</li>
<ul>
<li><span style="white-space: pre;"> </span>- C: <span style="color: #b45f06;">assert(a > 0);</span> // meaningful explanation</li>
<li><span style="white-space: pre;"> </span>- C#: <span style="color: #b45f06;">Debug.Assert(a > 0, "Meaningful explanation");</span></li>
<li><span style="white-space: pre;"> </span>- Go: <span style="color: #b45f06;">if a <= 0 { panic("meaningful explanation") }</span></li>
</ul>
<li><b><span style="color: #3d85c6;">Exceptions</span></b> Another thing that there has been a lot of complaint about is Go's lack of exceptions. Admittedly, there are many complexities caused by exceptions (such as very subtle undefined behaviors in C++) but I think it is more a reaction against the rampant misuse of exceptions in much Java code (either that or because modern exception handling was essentially a C++ invention and we don't want anything from C++ in Go :). But again we discover that Go does have exceptions but uses the keywords panic and recover, instead of throw and catch.</li>
<li><b><span style="color: #3d85c6;">Error Handling</span></b> So Go does have exceptions (ie panic/recover) but according to the Go ethos (ie, autocratic pronouncement) this mechanism is only supposed to be used for handling software failures (ie, bugs) not errors. The problem with this is that the distinction between a bug and an error is not always straightforward (eg, see <span style="color: #3d85c6;">Error Handling vs Defensive Programming</span> in my <a href="http://devmethodologies.blogspot.com.au/2012/05/defensive-programming.html"><span style="color: blue;">Defensive Programming</span></a> post); moreover the Go standard library itself often uses panic in situations that are clearly errors, not bugs. Go does have a few tricks (like defer, multiple-return values, the error type, etc) that make error-handling a bit easier than in C, but the simple fact is that in many situations (and without using panic) error-handling in Go can be a mass of complex, repetitive code. (Of course, Rob Pike and others deny this and demonstrate approaches that are unconvincing, being either just as complex or not universally applicable.)</li>
<li><b><span style="color: #3d85c6;">Reference Types</span></b> Go has pointers but it also has reference types (slices, maps, interfaces, chans, and functions) and the way reference types work is complex. For example a nil slice is treated exactly the same as an empty slice (except when you compare the slice to nil, of course) - and these sorts "split personality" behaviors lead to confusion (like arrays and pointers in C). You can also treat nil maps the same as empty maps <i>except</i> that you can't assign to an element of a nil map.</li>
<li><b><span style="color: #3d85c6;">Value/Pointer Receivers</span></b> The rules about when receivers are converted is confusing. Moreover there seem to be contradictory conventions: (1) use a value receiver for "const" methods and a pointer receiver for methods that modify the receiver (in lieu of "const" methods - see <b><span style="color: #0b5394;">Not C++</span></b> point 5) and (2) use a pointer for large types (such as a large struct or an array).</li>
<li><b><span style="color: #3d85c6;">Implicit Typing</span></b> Implicit typing is achieved very simply in Go by using := instead of = for the first use of a variable. (Implicit typing has become very popular - int recent years it has been added to C# [var], C++ [auto], Rust [let] etc.). However, my experience is that I am continually adding/removing explicit declarations, converting between = and := and moving statements into or out of the initialization part of if statements. This (along with shadowing mentioned above) makes refactoring code tedious and error-prone.</li>
<li><b><span style="color: #3d85c6;">Memory Allocation Performance O</span></b>ne thing that makes me a little uncomfortable is not knowing where the memory for a variable is coming from. In other languages you know if memory is being allocated from the stack or the heap; but in Go you just have to trust the compiler. I must admit that I have not yet encountered any performance problems but I can't shake the nagging feeling that I (or someone else) may make some innocuous code change and suddenly a lot more memory allocations need to be done from the heap. (My benchmarks have shown that this could slow them by more than 20 times!!)</li>
<li><b><span style="color: #3d85c6;">Unit Tests</span></b> Tests are so easy to write but there is one fatal flaw - tests are part of the package. Anyone with any experience of unit testing knows that tests should only test through the public interface (ie Go automated tests should not be part of the package) otherwise test maintenance becomes far too burdensome (see <a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-white-box-testing.html"><span style="color: blue;">White Box Testing</span></a>).</li>
<li><b><span style="color: #3d85c6;">Formatting</span></b> Having programmed in C and syntactically similar languages for almost 4 decades I have encountered a lot of different code formatting and debates on the merits thereof. Personally, I have always strictly conformed to K&R styling rules (even including the slight variations with the release of the 2nd edition of the book) with one important exception - I always place an opening brace on a line by itself. I started doing this in C in the mid-1980's and have been doing it ever since (in C/C++/C# etc). It makes the code easier to scan and I believe it has avoided numerous bugs and build problems by doing this.</li>
</ul>
<div>
<br /></div>
<span style="color: #3d85c6; font-size: large;"><b>Conclusion</b></span><br />
<br />
I started writing this post many months ago and it keeps changing as I learn more about Go. I have now been using Go for almost six months. I have really found that Go makes life so much easier than any other language I have used, in many many areas. On occasion I yearn for an STL container or algorithm but generally you can do a lot of useful stuff in Go.<br />
<br />
That said, there are a few things that I really don't like. Possibly the main one is the <b><span style="color: #990000;">condescending attitude</span></b> of the creators of the language. (I have also detected this to different extents in Smalltalk, Pascal, and Java.) In fact one of the things that I believe turned programmers away in droves from Pascal and towards C in the 1980's (me included) was treating programmers like idiots. Note that I am all in favor of making languages safer, as everyone makes mistakes, but not if it gets in the way of doing things properly.<br />
<br />
I guess a good example of this is the fact that it is mandated exactly how code should be formatted. If you get the formatting wrong the code won't even compile. To be honest, I actually like the formatting rules, except for one biggy - that <b><span style="color: #990000;">a left brace cannot be on a line by itself</span></b>, but must be a the end of the preceding line. This convention (from K&R) is an anachronism from a time of paper terminals. In my experience it makes code hard to read and leads to bugs. (In fact I seem to recall Brian Kernighan stating in an interview that the only reason they chose this convention was to keep down printing costs in the original edition of <b><i>The C Programming Language</i></b>.)<br />
<br />
On a practical note, Go does a good job of avoiding many errors that occur in C. However, in one area, it greatly magnifies the problem - Go makes it extremely <b><span style="color: #990000;">easy to create bugs by accidentally shadowing a variable</span></b>. (In fact just last Friday I discovered another bug of my own due to this.) Something urgently needs to be done about this.<br />
<br />
Finally, I just realized that I was going to explain how Go error-handling could be improved, without resorting to exception-handling. Writing error-handling code in Go, like C, is tedious - the sort of job a computer should do. I have a proposal to relieve the tedium but I've rambled on long enough for now so I will have to leave you in suspense until next time.<br />
<br />
<b><span style="font-size: large;">Next Month: A Proposal for Better Go Error-Handling</span></b><br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com2tag:blogger.com,1999:blog-7237530825191390698.post-4768179203036681072017-05-08T10:07:00.002+10:002017-05-08T10:07:33.108+10:00Why I like C#<div style="border-width: 100%; direction: ltr;">
<div style="direction: ltr; margin-left: 0in; margin-top: 0in; width: 6.109in;">
<div style="direction: ltr; margin-left: 0in; margin-top: 0in; width: 6.109in;">
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
I was going to talk a bit more about version control and Git after my posts on
Agile version control late last year but I have been very busy with a new job.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
“it was 20<br />years ago today”</span></div>
However, I have had a draft of this post for many years and significantly it was 20 years ago today (actually last Thursday) that I invented C#. I remember it distinctly as a
colleague suggested we go out and celebrate "Star Wars Day" after work. I had never heard of Star Wars Day (May the Fourth) before
then.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
It was during a jovial conversation over a few drinks that I mentioned my idea
that Microsoft should invent their own language which, as it turned out, was
rather like C#. The reaction was that I was a complete idiot, after all
Microsoft were not known for that sort of thing - the closest they had come was
COM (Component Object Model) which we had all used and agreed was an unwieldy
mess. Microsoft had also invested heavily in their own dialect of Basic called
VB (Visual Basic), as well as their C compiler, so why would they want a new
language? This was in the days when it was novel for a company to create a language, begun, I guess with Sun and Java.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
My idea was oddly triggered by my problems with the latest Visual C++ 4.0 (which we had
been using for a few months). I had written a new SCSI library in C++ for some
32-bit code but was greatly dismayed to find that VC++ was not designed to
create 16-bit code (for MSDOS, Windows 3.1) or even Win32s - I wanted to use
the C++ code with some legacy C applications.<br />
<br />
We had also encountered lots of frustrations with C++. We had done a lot of stuff in C previously but needed some modern languages features. Other languages around like Delphi and Java were not suitable either.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
I
decided that what was really needed was a language that Microsoft would
properly support (C++ support was not good at the time), had modern features
that C was lacking (like templates, exceptions and even a few niceties from Java, like GC). There was also a technological development (see next), where Microsoft was at the
forefront, which was crucial for my new language.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<b><span style="color: #0b5394; font-size: large;">P-Code</span></b></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
I
had been greatly intrigued by p-code since 1978 when I had first used Pascal at
University. Pascal (at least the compiler I used) compiled to p-code which
thence required a p-code interpreter for whatever CPU you were using. (This
idea was later used Java in byte-code and .Net MSIL.) Not long after that I did
a lot of programming in Forth (sort of a p-code assembler) on my Commodore 64.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
The
problem with p-code is that it is slow. Running p-code (via interpreter) is
about an order of magnitude slower than the same program compiled to native
instructions. A lot of people thought that this would become less of a problem
as computers got faster. The trouble with this argument is that while the interpreted code got faster so did the native code. (The idea of p-code
also seemed to be fading until Sun created Java, but a lot of people did not
like the poor performance of Java.)</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
However,
some people at Microsoft realized that once processors were fast enough you
could compile on the fly (later called JIT-compilation) rather than interpret
the p-code. Sooner or later the compilation time would become negligible.</div>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
"once processors<br />were fast enough<br />you could compile<br />on the fly"</span></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
Microsoft
had done a lot of research on JIT-compilation, on their (then) flagship language VB. (Basic is an interpreted like p-code). During the mid
1990s I did some tests and found that VB6 was similar in speed to C++ in many
areas due to use of JIT-compilation. All the C++ programmers I told this to
just did not believe me (or did not want to).</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #0b5394; font-size: large;"><b>Why
Microsoft needed a new language in 1997</b></span></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<ol style="direction: ltr; font-family: Calibri; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;" type="1">
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;" value="1"><span style="font-size: 11pt;">C (and an emerging C++) were the driving force behind almost all the successful MSDOS and Windows products and most C/C++ programmers, myself included (perhaps
unfairly), avoid VB like the plague.</span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">C/C++
development was painful and slow. COM was supposed to address this but
made it worse!</span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">There
were a lot of error-prone areas in C/C++ that could be fixed by new syntax
and semantics.</span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">There
were a lot of things that could be taken from C++ like exceptions,
templates and STL containers.</span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">They
could wrap/hide the horrendous Windows API (like MFC did for C++).</span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">There
was a lot of interest in Java (especially its innovative memory management
system) but Microsoft were impeded using Java for their own ends by a
litigious Sun. (Sun had already successfully sued Microsoft for not
properly implementing Java.)</span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">A language like Java generating intermediate code (p-code) would be slow but this problem could be alleviated by Microsoft's research into JIT-compilation from the early-mid 1990's.</span></li>
</ol>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<b><span style="color: #0b5394; font-size: large;">.Net
and C#</span></b></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
I did not really think much more about it but a few years later I started hearing about NGWS, VB7 and later C#. In 2001 I
downloaded and tried the C# public beta. It was then that I realized that C#
was very similar to the language that I had previously been advocating. My only
disappointment was that C# lacked templates and STL-like containers, though C#
2.0 later added generics.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
To
be fair to Microsoft (and Anders) there were a hell of a lot more great things
in C# than I could ever have come up with, though many came from Java and C++.
And even since then, C# has added some brilliant new things of its own, like
lambdas and LINQ.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<b><span style="color: #0b5394; font-size: large;">C#
Problems</span></b></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
You
may have noticed from previous posts that I like C# in many ways. I guess this may be partly due to the fact
that I feel I independently invented it. However, there are a few things that it got wrong, but remember that these are very small in number compared to the large number of
things it got right. (Also note that
some of these things are due to the .Net CLR upon which C# depends.)</div>
<ol style="direction: ltr; font-family: Calibri; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;" type="1">
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;" value="1"><span style="font-size: 11pt;">One thing that I really thought C# should have had from
the start was (what came to be known as) generics. In 1997 I had become a huge fan
of templates, and especially the STL, in C++. I remember reading that they would be added later (and were added in C#
2.0). Why not delay the release of C# 1.0 until they were ready? This has
caused a lot of problems of maintaining backward compatibility, especially
when implementing generic interfaces.<br /></span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">I
really hate the containers in C# compared to C++ STL containers or even
those of other languages. Related to the previous problem is the later
addition of generic containers to replace the earlier ones.<br /></span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">Apart
from the containers most of the C# run-time library is excellent. But there
were some simple, obvious mistakes which I picked up straight
away. An obvious one was that Int.Parse() throws an exception if it
encounters a non-digit rather than the more sensible behavior of something like C's strtoi(). This was later addressed with Int.TryParse().</span><br />Another one I encountered almost straight away is that String.Substring() throws an exception if the string is not long enough. This might be good behavior sometimes but more commonly you would just want a shorter string returned rather than throw an exception.<br /></li>
</ol>
<ol style="direction: ltr; font-family: Calibri; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;" type="1">
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;" value="4">One of the stupidest things in C# is the Decimal type.
(Anders seems to have an irrational penchant for stupid numeric types such
as the Delphi real48.) As soon as I saw it I thought it would be better
and much simpler just to add fixed point facilities to existing integer
types, attached as metadata (ie, using an attribute attached to an integer
variable).<br /><br />I wrote at length about this over a decade ago - eg see <a href="https://www.codeproject.com/Messages/994649/Re-Why-do-we-need-decimal.aspx"><span style="color: blue;">Why do we need Decimal</span>?</a><br /></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">Const
is one of the simplest and most useful additions to C++. I do not know why
C# (and other languages) continue to ignore it. </span>TBD: elaborate?<br /></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">The
fact that all static and heap variables are cleared (made zero) at
run-time is sometimes unnecessary and inefficient. What's the point of a huge array being
initialized to zeros then immediately have all its values set to some
other value(s)? (Note that the
security argument is a furphy.)<br /></span></li>
<li style="margin-bottom: 0; margin-bottom: 5pt; margin-top: 0; margin-top: 5pt; vertical-align: middle;"><span style="font-size: 11pt;">I
previously mentioned that the behavior of the default test for equality
(Object.Equals()) is flawed. (See the C# section in my post on <a href="http://devmethodologies.blogspot.com.au/2011/11/zero.html">Zero</a>).
Actually having recently used Go (the language from Google) I now
realize that all the "object-oriented" stuff, that C# copies
almost exactly from Java, is unnecessary and actually encourages poor
designs (but at least there is no multiple-inheritance!). I may talk about this more in a future
post on Go.</span></li>
</ol>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #0b5394; font-size: large;"><b>Conclusion</b></span></div>
<div style="margin-bottom: 5pt; margin-top: 5pt;">
<div style="font-family: calibri; font-size: 11pt;">
<br /></div>
<div style="font-family: calibri; font-size: 11pt;">
<span style="font-size: 11pt;">C# made things so much easier after using C (and then C++) for decades. There are so many things I could mention but a few immediately spring to mind:</span></div>
<ul>
<li><span style="font-family: "calibri";"><span style="font-size: 14.6667px;">metadata system which avoids all sorts of configuration problems that plague C due to header files, linking issues, DLL hell, etc</span></span></li>
<li><span style="font-family: "calibri";"><span style="font-size: 14.6667px;">the garbage collected heap which frees you from the tedium of having to track who allocated what and who needs to free it and making sure there are no memory leaks and double-frees, etc</span></span></li>
</ul>
<div>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">But there were many other little things - for example,</span></span><span style="font-family: "calibri"; font-size: 11pt;"> see the Code Project article that I wrote in 2004 called </span><a href="https://www.codeproject.com/Articles/7776/Arithmetic-Overflow-Checking-using-checked-uncheck" style="font-family: calibri; font-size: 11pt;"><span style="color: blue;">C# Overflow Checking</span></a><span style="font-family: "calibri"; font-size: 11pt;">.</span></div>
<div>
<br /></div>
<div style="font-family: calibri; font-size: 11pt;">
<span style="font-size: 14.6667px;">Sure C# borrowed a lot of things from Java, but that is de rigeur for language design (and Java got a lot from C++).</span></div>
<div style="font-family: calibri; font-size: 11pt;">
<br /></div>
</div>
</div>
</div>
</div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-16133696345588813612016-11-17T11:25:00.001+11:002016-11-17T11:25:11.582+11:00Overview<br />
<span style="color: #666666;">Here are links to all of my posts so far, loosely categorized.</span><br />
<br />
<span style="color: #666666;">Note that there are a few bonus links to my Code Project articles - marked with [CP] </span><br />
<br />
<br />
<span style="color: #0b5394;"><span style="font-size: x-large;">Software Design</span></span><br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Design Principles</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2011/10/handling-software-design-complexity.html" target="_blank">Handling Software Design Complexity</a> - what software design all boils down to<br />
<a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE</a> - an obvious thing we often forget<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/importance-of-developer-quality.html" target="_blank">Developer Quality Attributes</a> - or why fixing bugs is <i><b>not</b></i> important<br />
<span id="goog_1873098402"></span><span id="goog_1873098403"></span><a href="http://devmethodologies.blogspot.com.au/2012/11/verifiability.html" target="_blank">Verifiability</a> - software is useless unless you can verify its correctness<br />
<a href="http://devmethodologies.blogspot.com.au/2012/03/code-degradation.html" target="_blank">Why Good Programs Go Bad</a> - risk avoidance causes software to "rust"<br />
Book Review: 97 Things Every Architect Should Know<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Design Practices</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/08/fundamentals-of-software-design.html" target="_blank">Fundamentals of Software Design</a> - 8 ways to create a good design<br />
<a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">Agile Design</a> - how emergent design almost always works better than BDUF<br />
<a href="http://devmethodologies.blogspot.com.au/2012/06/inversion-of-control.html" target="_blank">Inversion of Control</a> - IOC is a technique for better decoupling using DIRE<br />
<a href="http://devmethodologies.blogspot.com.au/2012/07/dependency-injection.html" target="_blank">Dependency Injection</a> - an example of IOC<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Anti-Patterns</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/12/the-gas-factory-anti-pattern.html" target="_blank">Gas Factory Anti-Pattern</a> - a mistake even (or especially) good designers make<br />
<a href="http://devmethodologies.blogspot.com.au/2012/11/reusability-futility.html" target="_blank">Reusability Futility</a> - "Simplicity before Generality, Use before Reuse"<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/shotgun-initialization.html" target="_blank">Shotgun Initialization</a> - an example of the dangers of defensive programming<br />
<a href="http://devmethodologies.blogspot.com.au/2012/10/the-layer-anti-pattern.html" target="_blank">Layer Anti-Pattern</a> - the problems of a common, obvious approach<br />
<br />
<br />
<span style="color: #0b5394;"><span style="font-size: x-large;">Agile</span></span><br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Principles</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2014/09/agiles-fifth-element.html" target="_blank">Agile's Fifth Element</a> - favor simple design over re-usability and generality<br />
<a href="http://devmethodologies.blogspot.com.au/2014/04/jit.html" target="_blank">JIT (Just In Time)</a> - an example of DIRE that is core to much of Agile<br />
<a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE (Don't Isolate Related Entities)</a> - <i>how</i> you divide and conquer is the key<br />
<a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">Agile Design</a> - evolving software one small step at a time<br />
<a href="http://devmethodologies.blogspot.com.au/2012/11/reusability-futility.html" target="_blank">Agile and Code Reuse</a> - all about YAGNI (you ain't gonna need it)<br />
<a href="http://devmethodologies.blogspot.com.au/2012/07/sqa-and-agile-methodologies.html" target="_blank">Software Quality Assurance & Agile</a> - how Agile evolved from, but is different to, SQA<br />
<a href="http://devmethodologies.blogspot.com.au/2015/01/lean-is-not-agile.html" target="_blank">Lean is not Agile</a> - applying "eliminate waste" to software design leads to BDUF<br />
<a href="http://www.codeproject.com/Articles/124732/Software-Development-Methodologies" target="_blank">Software Development Methodologies</a> [CP] - Agile and other methodologies by analogy<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Team</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2015/03/scrum-team-size.html" target="_blank">Scrum Team Size</a> - teams should be small to avoid social loafing and other phenomena<br />
<a href="http://devmethodologies.blogspot.com.au/2015/04/scrum-team-composition.html" target="_blank">Scrum Team Composition</a> - "feature" teams are the key<br />
<a href="http://devmethodologies.blogspot.com.au/2015/04/team-collaboration.html" target="_blank">Collaboration</a> - traditional development discourages collaboration + why Scrum works<br />
<br />
<span style="color: #3d85c6;"></span><span style="color: #3d85c6;"><span style="font-size: large;">Making Agile Work</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/10/scrum-standup.html" target="_blank">Scrum Standup</a> - it's more about visibility than communication<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/importance-of-developer-quality.html" target="_blank">Developer Quality Attributes</a> - what benefits developers eventually helps users<br />
<a href="http://devmethodologies.blogspot.com.au/2016/09/agile-version-control.html" target="_blank">Agile Version Control</a> - Agile requires the right version control practices & software (Git)<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/scrum-problems.html" target="_blank">Scrum Problems</a> - management "buy-in" & other things that help Scrum work properly<br />
<a href="http://devmethodologies.blogspot.com.au/2013/01/why-scrum-fails.html" target="_blank">Why Scrum Fails</a> - intransigence, non-collaboration, etc<br />
<a href="http://devmethodologies.blogspot.com.au/2015/09/written-vs-verbal.html" target="_blank">Written vs Verbal</a> - when, who, why, and how of Agile documentation<br />
<a href="http://devmethodologies.blogspot.com.au/2012/01/jit.html" target="_blank">JIT Testing</a> - testing as you go (continuous testing) is an example of JIT (Just In Time)<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Unit Tests</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/10/change.html" target="_blank">Change</a> - how Unit Tests help you to embrace change<br />
<a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-whats-so-good-about-them.html" target="_blank">What's so great about Unit Tests</a> - Unit Tests are not about finding bugs<br />
<a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-white-box-testing.html" target="_blank">White Box Testing</a> - the best Unit Tests use "good" white box testing<br />
<a href="http://devmethodologies.blogspot.com.au/2013/12/unit-tests-personal-experiences.html" target="_blank">Personal Experiences with Unit Testing</a> - it took me 20 years to truly appreciate them<br />
<a href="http://devmethodologies.blogspot.com.au/2014/01/unit-tests-challenges.html" target="_blank">Challenges</a> - why getting started with Unit Tests seems, but is not, insurmountable<br />
<a href="http://devmethodologies.blogspot.com.au/2014/01/unit-tests-best-practice.html" target="_blank">Unit Tests Best Practice</a> - a few things to avoid<br />
<a href="http://devmethodologies.blogspot.com.au/2014/03/arguments-against-unit-tests.html" target="_blank">Arguments Against Unit Tests</a> - common arguments and why most are invalid<br />
<a href="http://devmethodologies.blogspot.com.au/2014/03/unit-tests-summary.html" target="_blank">Summary</a> - Unit Tests concisely summarized<br />
<br />
<br />
<span style="color: #0b5394;"><span style="font-size: x-large;">Coding</span></span><br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Essentials</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2011/11/zero.html" target="_blank">Zero</a> - bugs are less likely if you don't treat zero as a special case<br />
<a href="http://devmethodologies.blogspot.com.au/2012/12/asymmetric-bounds-and-zero-based.html" target="_blank">Asymmetric Bounds</a> - in code and GUI design this is an important way to avoid bugs<br />
<a href="http://devmethodologies.blogspot.com.au/2013/10/book-review-clean-code.html" target="_blank">Book Review: Clean Code</a> - a great book on creating the best code<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">C Coding</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/07/best-practice-in-c-for-modules.html" target="_blank">Best Practice in C for Modules</a> - strong-coupling and other things to avoid<br />
<a href="http://devmethodologies.blogspot.com.au/2012/05/defensive-programming.html" target="_blank">Defensive Programming</a> - how it works and how it can hide bugs<br />
<a href="http://devmethodologies.blogspot.com.au/2012/02/shotgun-initialization.html" target="_blank">Shotgun Initialization</a> - a defensive programming practice to avoid<br />
<a href="http://devmethodologies.blogspot.com.au/2013/04/alignment-and-pragma-pack.html" target="_blank">Alignment and #pragma pack</a> - make structs "alignment agnostic" to avoid surprises<br />
<a href="http://devmethodologies.blogspot.com.au/2012/11/verifiability.html" target="_blank">Making Code Testable</a> - coding for testability improves correctness, reliability, etc<br />
<a href="http://www.codeproject.com/Articles/357065/Ten-Fallacies-of-Good-C-Code" target="_blank">Ten Fallacies of Good C Code</a> [CP] - 10 more things to avoid<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">C++ Coding</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2013/05/stls-dark-secret.html" target="_blank">STL's Dark Secret</a> - vectors are slower than they should be<br />
<a href="http://devmethodologies.blogspot.com.au/2013/08/iterators-through-looking-glass.html" target="_blank">Iterators Through the Looking Glass</a> - subtleties of the STL reverse iterators<br />
<a href="http://devmethodologies.blogspot.com.au/2013/06/c11-and-lambda-functions.html" target="_blank">C++11 and Lambda Functions</a> - lambda functions make STL so much better<br />
<a href="http://devmethodologies.blogspot.com.au/2013/07/nesting-functions-using-lambdas_13.html" target="_blank">Nested Functions using Lambdas</a> - you can finally have nested functions in C++11<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">C# Coding</span></span><br />
<br />
<a href="http://www.codeproject.com/Articles/7776/Arithmetic-Overflow-Checking-using-checked-uncheck" target="_blank">Overflow Checking using checked/unchecked</a> [CP] - C# has some cool features<br />
<a href="http://devmethodologies.blogspot.com.au/2013/07/nesting-functions-using-lambdas_13.html" target="_blank">Nested Functions using Lambdas</a> - includes an example of using C# lambdas<br />
<div>
<br /></div>
<span style="color: #3d85c6;"><span style="font-size: large;">Maintainability</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/04/long-identifiers-make-code-unreadable.html" target="_blank">Long Identifiers make Code Unreadable</a> - don't try to put too much info. into a name<br />
<a href="http://devmethodologies.blogspot.com.au/2012/06/self-describing-code.html" target="_blank">Self Describing Code</a> - why it's a bad idea and why you should comment your code<br />
<br />
<span style="color: #3d85c6;"><span style="font-size: large;">Other</span></span><br />
<br />
<a href="http://devmethodologies.blogspot.com.au/2012/05/phillips-scale-of-code-quality.html" target="_blank">The Phillips Scale of Code Quality</a> - how good is your code?<br />
<a href="http://devmethodologies.blogspot.com.au/2016/11/version-control-personal-experiences.html">Version Control - Personal Experiences</a> - hands on version control<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-61251995114420391142016-11-17T10:13:00.000+11:002016-11-17T10:13:54.543+11:00Version Control - Personal Experiences<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
Last month we looked at how to use version control when using Agile
development. My conclusion was that you should be using Git. This is simply
because using CI (Continuous Integration) there is a lot of branching and merging going on and
Git is the only version control system that allows a version to have to have
two parents. This is not to say that you can't use other version controls
systems (and in fact I like SVN better in many ways - see below) just that Git
keeps track of what needs to be merged for you.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
This month I take a leisurely stroll back through time and look at all the version control systems I have used. <span style="font-size: 14.6667px;">I have a long personal history of using version control systems (generally being the administrator for such systems).</span><span style="font-size: 14.6667px;"> </span><span style="font-size: 11pt;">I have used the best (and worst) but you should note that there
are some excellent systems (like the proprietary </span><b style="font-size: 11pt;">Perforce </b><span style="font-size: 11pt;">and open-source </span><b style="font-size: 11pt;">Mercurial</b><span style="font-size: 11pt;">) that I
have not used (yet?).</span></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
<span style="color: #3d85c6; font-size: large;">UNIX</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
I first experimented with version control while at Sydney University in the
early 1980's using the Computer Science department's VAX 11/780. This ran a variation of UNIX
that included a primitive version control system called SCCS (Source Code
Control System) I think.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">PVCS</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
I first used version control for my C source code in
several MSDOS/C jobs during the mid-1980's. At the time the only serious option
for MSDOS was PVCS (Polytron Version Control System) which I used at several
companies.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
I can't say I loved PVCS but it did the job. It efficiently stored changes to text files as "reverse deltas" and had all the basic features like branching and tagging.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">CVS, etc</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
In the late 1980's I moved back to UNIX where I was a system
administrator and system programmer. Under UNIX I tried SCCS, RCS (Revision
Control System) and an early version of CVS (Concurrent Versions System) all of
which worked butwere difficult to use, in some way.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">TLIB</span></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
When I moved back to MSDOS/MSWindows systems in the early 1990's I used TLIB.
This was similar to PVCS, but quite a bit better. However, this was still a
command line driven system which I found tedious to use.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">VSS</span></div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
In the mid-1990's Microsoft included a GUI based version control system
with their Windows IDE (Developer Studio). This seemed like a great idea to me after my
experiences with command-line version control systems. However, Visual Source
Safe (VSS) turned out to be by far the worst product I have ever used - it was
not only poorly designed and very confusing, but also had a tendency to lose
and corrupt files and whole repositories! Moreover, it made multi-site
development impossible due to poor performance - there were 3rd party
extensions to VSS (I later used one called VSSConnect) that were developed
purely to improve performance over the Internet - but even then the performance
was barely acceptable.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">ClearCase</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
In my next job I used ClearCase (originally developed by Rational before being
bought by IBM). This is the sort of product you would expect from IBM -
thorough but confusing due to its plethora of features and options and requiring a lot of work to maintain. Luckily, I
got to work on a new project where I had the opportunity to try a new
open-source control system called Subversion (SVN).</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">SVN (SubVersion)</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
I set up SVN as an Apache module on one of the companies servers and was amazed at the
performance. Using an Apache server allowed SVN to easily work over the Internet since it used HTTP/WebDav. (SVN also provides its own protocol and server call svnserve but the Apache option has advantages.)</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<span style="font-size: 11pt;"><br /></span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<span style="font-size: 11pt;">The team for this project was split between Australia and Belgium
but the two developers in Belgium got great performance (through VPN over the
Internet) even though the server was in Sydney. Generally we spent about 10 minutes a day updating and committing changes.</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
This success with SVN encouraged me to use SVN for my own personal
projects. I put my HexEdit open-source
software (see <a href="http://www.hexedit.com/">http://www.hexedit.com</a>) into
an SVN repository which was hosted on SourceForge.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
SVN was the first version control system I actually enjoyed using.
One reason was that there was a Windows shell extension called TSVN (Tortoise
SVN) that allowed you to easily do all your version control tasks using Windows
Explorer.</div>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
SVN was the first<br />version control system<br />I enjoyed using</span></div>
<br />
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
Another favorite thing is that, even if you are disconnected from
the repository (eg if Internet connection is lost), you can still compare your
current changes with the repo. This is because SVN keeps a local copy of all
files as they were when you last updated from the repository.</div>
<div style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">TFS</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
In my next job I found that I was again dealing with the horrible
VSS. Luckily, the company decided they
had had enough problems with VSS and moved to TFS. Now TFS is much much better
than VSS but still inferior in many ways to SVN. <span style="font-size: 11pt;">TFS does provides "shelving" which is a good idea but I have not found it all that useful in
practice.</span></div>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
TFS does not<br />conform to the<br />Observer Pattern</span></div>
<br />
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
TFS is more of a "centralized control" system than SVN.
For example, it keeps track of all the files you have checked out into your WC (working copy) in
its central database, whereas SVN only stores the actual files (the repo) in
its central database and tracks things to do with the WC locally. <span style="font-size: 11pt;">To me the SVN approach makes more sense (conforming to the </span><span style="font-size: 14.6667px;">"Observer Design Pattern") and indeed many developers encounter </span><span style="font-size: 11pt;">problems when the local WC becomes inconsistent with TFS's idea of what it should contain.</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; margin-bottom: 5pt; margin-top: 5pt;">
<span style="color: #3d85c6; font-size: large;">Git</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
Finally, I last came to try Git a few years ago as I was intrigued
by its branching model. This solved the
only annoying thing I found with SVN - the problem of merging changes between
the trunk and a long term branch. I like to merge often (as Agile and CI say
you should) but SVN forced you to manually keep track of which versions you
have already merged between branches.
Git automatically tracks your merges so you can't forget to merge or
merge the same thing twice.</div>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
Git makes it easy<br />to branch and<br />merge</span></div>
<br />
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
There is a lot to like about Git but in all honesty I do not find it
as enjoyable to use as SVN. First, there are a plethora of confusing commands
and options. For example the ability to "stage" a commit before
actually committing I never found that useful. It just adds another layer of
complexity.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
But the worst thing about Git is that it is all command line driven.
I always find it much easier to remember how to use GUI software than to
remember obscure command names and options. Luckily Atlassian provides a GUI
interface to Git using a free product called SourceTree.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br />
One good thing about Git is that it has an excellent book called "Pro
Git" that explains in detail how to use it. However the book does get a
little evangelical in its praise for Git at times. For example, it goes on
about atomic commits (SVN has atomic commits), how fast it is to clone a repo
(SVN checkout is faster) and that it has the killer feature of lightweight branching (SVN has that too).</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
Then there is the fact that Git is distributed whereas SVN is centralized. <span style="font-size: 11pt;">Now people rave on and on about the advantages of distributed
version control but I really don't see it.</span><span style="font-size: 11pt;">
</span><span style="font-size: 11pt;">Sure if you have an open-source project with one or more different
"forks" then it's probably useful. Personally I prefer one central
"master" copy of the source where changes are merged to as soon as
possible. I think having multiple repositories floating around would lead to a
merge nightmare and contravenes the idea behind CI.</span></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
Anyway, I don't want to go into too much depth on the "centralized vs distributed" debate here (I may later). So that's all for now. Bye.</div>
<div lang="en-US" style="font-family: Calibri; font-size: 11.0pt; margin-bottom: 5pt; margin-top: 5pt;">
<br /></div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-67814392223956285742016-09-26T11:12:00.002+10:002016-09-26T11:16:47.617+10:00Agile Version Control<b><span style="color: #3d85c6; font-size: large;">Introduction</span></b><br />
<br />
A mistake often made when adopting Agile is insisting on certain Agile practices and outcomes without converting to using the necessary tools and techniques (see the <span style="color: #6fa8dc;">CASE STUDY</span> below for an example). This is one major deficiency of Scrum or, at least, of using Scrum by itself. Scrum does not require necessary development tools (and even some essential processes) that allow Agile to work. I have talked about this previously (eg the <b><span style="color: #3d85c6;">Summary </span></b>of <a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-whats-so-good-about-them.html" target="_blank"><span style="color: blue;">November 2013 post</span></a>).<br />
<br />
A crucial practice in Agile is Continuous Integration (CI). CI is difficult, if not all but impossible, without certain tools and practices, such as automated builds (ye olde build box), <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank"><span style="color: blue;">Agile (JIT) Design</span></a>, etc. I will also mention <a href="http://devmethodologies.blogspot.com.au/2014/03/unit-tests-summary.html" target="_blank"><span style="color: blue;">Unit Tests</span></a> here (again :) as without their safety net you cannot hope to make CI work. CI also depends on using a modern version control system, like Git, and using it in the right way. This is what I want to talk about.<br />
<br />
<div style="background-color: #f1f1f1; margin: 6px; padding: 6px;">
<span style="color: #3d85c6;">CASE STUDY</span><br />
A few years ago I was working on a project where management insisted on a move to Agile with the aim of creating new software releases every few weeks, instead of every few months, as was previously done (ie, about 4 to 6 times more frequently). However, no new tools or development infrastructure was introduced to facilitate this. Moreover essentially the same procedures were used. The development procedures alone were onerous, but not as bad as testing and release procedures (of which I had little understanding and will make no comment).<br />
<br />
For an unlucky developer there was a tedious and error-prone procedure for every new release. It was bearable when done a few times per year but less bearable when it had to be done more often. This was a typical Waterfall development approach where the project was branched for the new release so that bug fixes could be made on the branch without affecting ongoing development. (I will explain this sort of approach in detail below.)<br />
<br />
The major steps were essentially<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>• Branch the project in VSS, then delete some of the unneeded branched files<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>• Branch and move some global headers shared between projects<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>• Manually modify project files to handle VSS problems and change global header locations<br />
<br />
This whole process usually took one developer at least a day if everything went well. This is <i>not</i> an exaggeration, though the whole process was exacerbated by the use of VSS and a large manual process that should have been automated.</div>
<br />
I will get to the point of this post in a moment but first I give a brief overview of how version control relates to the development process and how it was used before Agile came along.<br />
<br />
<b>NOTE: </b>If you are familiar with version control concepts then you can skip to the <b><span style="color: #3d85c6;">Continuous Integration</span></b> section below.<br />
<div>
<br /></div>
<b><span style="color: #3d85c6; font-size: large;">Version Control</span></b><br />
<br />
All version control systems allow you to keep track of the changes made to source files. One advantage of this is that you can see how the software has evolved over time. This can provide a deeper understanding of code than can be obtained by just looking at the current state. Being able to compare source files from different times is invaluable when investigating why a change was made, how bugs were introduced, etc.<br />
<br />
Moreover, you can get a snapshot from any point in time. For example, in the diagram below you could use the version control system to "checkout" the source as it was at the time of Release 1.0. You can then build that specific version if you need to investigate its behavior.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivF4NddpGkT9vfoNh-uThhzT5ne6cCtWqOq8ceF12MyvrmOFSES3xQquxvETznNPk6-ZcO3b2mBNmSteSoEYpUeSbrZU5dH3ebQRF42GFudXlHq9JzYt7MSuMAm4YX6gJ2wCosgXo7_yg/s1600/VersionControlLinear.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="65" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivF4NddpGkT9vfoNh-uThhzT5ne6cCtWqOq8ceF12MyvrmOFSES3xQquxvETznNPk6-ZcO3b2mBNmSteSoEYpUeSbrZU5dH3ebQRF42GFudXlHq9JzYt7MSuMAm4YX6gJ2wCosgXo7_yg/s400/VersionControlLinear.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;"><b>Diagram 1. Basic Version Control</b></span></div>
<br />
Each box in the diagram represents a check-in of one or more files. Of course, this is a simplified diagram - real projects have many more check-ins (hundreds or even thousands).<br />
<br />
Another essential facility of a version control system is branching. This allows variations to be developed from a common base version. Traditionally, branching has two uses:<br />
<ul>
<li>release branching - a branch is created when a new version is released</li>
<li>feature branching - a branch for an experimental or long-term development</li>
</ul>
<br />
<b><span style="color: #3d85c6; font-size: large;">Release Branching</span></b><br />
<br />
Release branching (sometimes called fix branching) is very common (if not ubiquitous) in pre-Agile development. It allows released versions to be quickly fixed while not interfering with ongoing development. For example, consider a software project with two releases: versions 1.0 and 1.1, with ongoing development on version 2.0.
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 210px;">
<div style="text-align: center;">
<span style="font-size: x-small;"><b><u>Version Control Jargon</u></b></span> </div>
<span style="font-size: x-small;"><b><br /></b></span>
<span style="font-size: x-small;"><b>Repository</b> (repo) = file historical storage</span><br />
<span style="font-size: x-small;"><b>Checkin</b> = add or update file(s) to the repo</span><br />
<span style="font-size: x-small;"><b>Checkout</b> = obtain a local copy of file(s)</span><br />
<span style="font-size: x-small;"> usually in order to update and checkin</span><br />
<span style="font-size: x-small;"><b>Commit (v)</b> = checkin</span><br />
<span style="font-size: x-small;"><b>Commit (n)</b> = files that were checked in</span><br />
<span style="font-size: x-small;"><b>Merge</b> = combine changes from 2 sources</span><br />
<span style="font-size: x-small;"><b>Working Copy</b> (WC) = local copy of files</span><br />
<span style="font-size: x-small;"><b>HEAD</b> = pointer into the repo for the WC,</span><br />
<span style="font-size: x-small;"> usually the most recent commit on the trunk</span><br />
<span style="font-size: x-small;"><b>Branch</b> = fork in version history</span><br />
<span style="font-size: x-small;"><b>Trunk</b> = ongoing development "branch"</span></div>
<br />
Now imagine that a user has found a critical bug in version 1.0 (Bug 2 in the diagram below). You can't reproduce the bug in the latest version but you can reproduce it in 1.0 (and 1.1). Of course, you can't simply give the customer a copy of 2.0 as they have not paid for the new features and, in any case, it is not ready for release. You need to provide a fix for version 1.0.<br />
<br />
You check out the code for 1.0 to view and debug it and quickly find the problem. Now you can check-in your fix to the branch for version 1.0. You also port and check-in the fix to the version 1.1 branch as well. (For completeness you also check why the bug no longer occurs in 2.0 - it may simply be hidden by other changes or obviated by some later development.)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6WQCU-xVmF_v7JkQ8QVoSz8XGYVF4Ls5YhKg9bShOzaFOFBiooMOmyAbRhyphenhyphenhqz4FihBDyW7nimw8y_cELtDhrhTDLAyXOG_8xlKYNEGI5lHHF1E437iT_SmvHkFKFinqmwU6vr1VnO9k/s1600/VersionControlBranched.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="132" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6WQCU-xVmF_v7JkQ8QVoSz8XGYVF4Ls5YhKg9bShOzaFOFBiooMOmyAbRhyphenhyphenhqz4FihBDyW7nimw8y_cELtDhrhTDLAyXOG_8xlKYNEGI5lHHF1E437iT_SmvHkFKFinqmwU6vr1VnO9k/s400/VersionControlBranched.png" width="400" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 2. Release Branching</span></b></div>
<br />
<b><span style="color: #3d85c6; font-size: large;">Feature Branching</span></b><br />
<br />
Feature branching is traditionally used for a development that needs to be separate from the main ongoing development. This may happen for various reasons:<br />
<ul>
<li>the development is experimental and may not prove to be viable</li>
<li>the development is not certain to be needed (eg, for proposed legislation)</li>
<li>the development is for a large feature that overlaps with other release(s)</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8LXhpVaM3R05vAczW9DUmK2Ygvu0najjUoyMyraVK-8h3P5glAw6UawXXqgliSuHtAo8m9MoeABosB6K8xoBWoqnyF90GoXkR0XeCAVW6swjvr2_BlAgMlaTPhEAg2OLZaxAMd-lvDBM/s1600/VersionControlFeatureBranch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8LXhpVaM3R05vAczW9DUmK2Ygvu0najjUoyMyraVK-8h3P5glAw6UawXXqgliSuHtAo8m9MoeABosB6K8xoBWoqnyF90GoXkR0XeCAVW6swjvr2_BlAgMlaTPhEAg2OLZaxAMd-lvDBM/s400/VersionControlFeatureBranch.png" width="400" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 3. Feature Branching</span></b></div>
<br />
These branches are always intended to be merged back into the trunk, but it can happen that the branched code is not required and so is discarded, eg if the experimental development is found not to be viable.<br />
<br />
I have been involved with a few feature branch developments and they are notoriously tedious and troublesome. The first problem to avoid is that by the time the feature branch is merged back into the "trunk" there are so many incompatibilities caused by the divergent code that it can be difficult or even impossible to merge the differences. In this case a great deal of work is required to integrate the changes and often this involves workarounds and kludges that corrupts the integrity of the software design. It's not uncommon for the feature to have to be completely rewritten to be compatible with the current ongoing project.
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #134f5c; font-family: "georgia" , "times new roman" , serif; font-size: large;">
“feature branches<br />can be difficult <br />or impossible <br />to merge”</span></div>
<br />
<br />
Because of the above problem developers have learnt to <b><i>"merge early and often"</i></b>. That is, changes on the trunk should be regularly merged into the feature branch to avoid divergence. Of course, this is a tedious and time-consuming process that tends to get skipped due to more urgent tasks. It often also requires discussions between members of the feature and maintenance teams to understand what the code does and how best to merge the differences.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvk1qJL1dj4q22TmF61HTMT2UlXpyprLvh_2g2fwf_wn5JCmsR8CiuYcM3TFR02y9kEEMLVSbuZUBl1aQka_omShRKELIBTq27nsLjLxDXRsIOHAqabKLtsZPaFTfV7XJEGouCSq5VjKk/s1600/VersionControlMerge.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvk1qJL1dj4q22TmF61HTMT2UlXpyprLvh_2g2fwf_wn5JCmsR8CiuYcM3TFR02y9kEEMLVSbuZUBl1aQka_omShRKELIBTq27nsLjLxDXRsIOHAqabKLtsZPaFTfV7XJEGouCSq5VjKk/s400/VersionControlMerge.png" width="400" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 4. Merging Trunk Changes</span></b></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRzx3FFQgbcAY5T2lv70-BR6XyFJRYmu6BU_fE91TYWP92LhA1br1Nbih_6cDVxnTsygp-5b6cNgEWCPJd1G97q0caVjsESPdH02CdOD0NT9ARLG3lKcxvNHrxtAt6uogX9l_yJDVafRA/s1600/VersionControlFeatureEFinal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRzx3FFQgbcAY5T2lv70-BR6XyFJRYmu6BU_fE91TYWP92LhA1br1Nbih_6cDVxnTsygp-5b6cNgEWCPJd1G97q0caVjsESPdH02CdOD0NT9ARLG3lKcxvNHrxtAt6uogX9l_yJDVafRA/s400/VersionControlFeatureEFinal.png" width="400" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 5. The completed feature is merged into the trunk</span></b></div>
<div style="text-align: left;">
<b><span style="font-size: x-small;"><br /></span></b></div>
<b><span style="color: #3d85c6; font-size: large;">Continuous Integration</span></b><br />
<br />
These sorts of problems of merging and integrating code (as well as other problems) led to the practice of <b><i>continuous integration</i></b> (CI) which is core to the Agile approach to software development. But even without Agile, CI avoids integration headaches, improves common understanding and communication in the team and generally results in a better design and less bugs. It is an example of <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a> since you are not isolating the new features from the rest of the code as it evolves.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Agile Approach</span></b><br />
<br />
CI enables the agile approach of delivering small improvements that slowly but surely moves the development towards the target. The target, of course, is the PO's understanding of what is needed and which may itself be moving.<br />
<br />
Each atomic development task, called a <b><i>User Story</i></b>, needs to be small enough to be completed in a few days (and certainly within the current sprint). If the task is larger than that, then it needs to be split up.
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 251px;">
<div style="text-align: center;">
<b>What is a User Story? </b></div>
<span style="font-size: x-small;"><br /></span><span style="font-size: x-small;"><b>User Stories</b> are used in Agile as a replacement for "specs". A User Story is a simple statement about a change or enhancement to the software. This is often written on a small card in the format:</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><b>As <A> I want <B> so I can <C></b></span><span style="font-size: x-small;"> where:</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><b><A></b> = the person/group requiring the enhancement -</span><br />
<span style="font-size: x-small;"> often a software user, but can be anyone</span><br />
<span style="font-size: x-small;"><b><B></b> = a simple description of the enhancement<br /> from the perspective of <b><A></b></span><br />
<span style="font-size: x-small;"><b><C></b> = the purpose or benefit of the enhancement -</span><br />
<span style="font-size: x-small;"> this can be skipped but I highly recommend it</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">A User Story is <i>almost </i>all the written documentation you need to specify all changes to the software. Of course, for a large feature you will have many <b>User Stories</b> grouped into an <b>Epic</b>.</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">The other written documentation you need is a handful of <b>Acceptance Criteria</b> </span><span style="font-size: x-small;">written on the back of the related User Story c</span><span style="font-size: x-small;">ard. These explain</span><span style="font-size: x-small;"> how you can check that a User Story is</span><span style="font-size: x-small;"> complete.</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><b>Example:</b></span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">As an administrator I want to be able to change my password so I can ensure the security of the system</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">Acceptance Criteria:</span><br />
<span style="font-size: x-small;">1. old password must be entered first</span><br />
<span style="font-size: x-small;">2. new password must be entered twice to catch typos</span><br />
<span style="font-size: x-small;">3. new password must be different to old password</span></div>
<br />
The common argument against this approach is that it is inefficient - it's better to understand the problem, come up with a solution and implement it all in a controlled manner. In theory this sounds like a good argument, in practice it doesn't work (see<span style="color: blue;"> <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">May 2014 post on Agile Design</a> </span>for more on the evils of BDUF). If BDUF did ever work as it's supposed to (which it very rarely - if ever - does) it <i>would </i>be more efficient. But even then the Agile approach is more reassuring to the PO/users/stakeholders; even in that worst case it still has the <i>perception</i> of greater productivity since everyone can see progress being made.<br />
<br />
A stronger argument against the Agile approach is that there are some complex tasks that cannot be decomposed into simpler ones - they cannot be tackled at all with an evolutionary approach. Again this may be theoretically possible but I have never encountered such a situation in practice. Once you get the hang of it, it's easy to find a way to work towards a goal while keeping the software useable and useful at every point along the way (or at least at the end of every sprint).<br />
<br />
The crucial point is that User Stories are designed such that at every stage the software can be used. At the end of every sprint the PO will have a working, bug-free piece of software that can be tested and even delivered to real users. To make this work you need a certain type of version control system.<br />
<br />
<b> So what sort of version control do you need for Agile?</b><br />
<br />
In the end many things in Agile - short sprints, small User Stories, JIT Design, feature teams, and CI - work together and depend on a version control system that allows easy branching and (especially) merging. Having a clumsy or manual merging process is not an option as User Stories are continually being merged back into the trunk.<br />
<br />
Conventionally version control systems treat the relationship between versions as a tree. If you look back at all the above version control diagrams (ignoring the dashed arrows) you will see that they are all tree diagrams. (I know, it's obvious that you need branches to form a tree.) Modern version control systems help you merge code between branches (the dashed arrows leading into the blue boxes) but you still need to manually keep track of where the merge comes from and which bits have been merged already.<br />
<br />
This is where Git comes in.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Git</span></b><br />
<br />
In my opinion Git is the only version control system that should be used for Agile development. Git has one killer feature - a version can have two parents. Git can automatically merge versions always keeping track of things so that it does not miss versions or try to merge the same thing more than once.<br />
<br />
This means that a version "tree" becomes instead a "DAG" (directed acyclic graph) because each version can have two - not just one - parents.<br />
<br />
Before I discovered Git I used another fine version control system called SVN (short for Subversion), starting about 10 years ago, and found it a joy to use except for one thing - on occasion I would need a long-term branch which was painful to keep updated with trunk developments. To avoid a nasty surprise when the branch had to be merged back into the trunk I regularly merged trunk code into the branch (as in <b>Diagram 5</b> above). However, to make sure that changes were not missed, or the same change merged more than once I had to manually keep track of what versions from the trunk had been merged into the branch. This was tedious and error-prone and something that Git does for you.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Agile Version Control</span></b><br />
<br />
Agile version control using Git is simple. A developer branches the code to work on a User Story. Git makes it easy to merge the branch back into the trunk. A simple example is shown in the following diagram where all User Story branches are merged back into the trunk by the end of each sprint.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPzZdSyNj9q2dW3QkSKzje4wRuqNHBLCkjnZiffJ_ycDyF_msUwIhpXVMfuDKFTkPysRQrzTyMfkEXpt8CYgVDyM9Rh9bjlDkfvtK0mD1pbjv9rUGeEpTl_QxM2l1hHg1zsHH13vateDg/s1600/VersionControlAgile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPzZdSyNj9q2dW3QkSKzje4wRuqNHBLCkjnZiffJ_ycDyF_msUwIhpXVMfuDKFTkPysRQrzTyMfkEXpt8CYgVDyM9Rh9bjlDkfvtK0mD1pbjv9rUGeEpTl_QxM2l1hHg1zsHH13vateDg/s320/VersionControlAgile.png" width="320" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 6. Agile Version Control</span></b></div>
<br />
However, generally you need control of what features are delivered to "production". This is often accomplished by having <b><i>dual streams</i></b> - an on-going "development" stream (or branch) and a separate "delivery" stream (trunk) allowing control over when features are delivered.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCXQnOh8FxZxWkDbxLG1Y1EA55l_zlhbPBHqDzx6HIm9gbJW1Y5IyTuR3T2LsoMzm_XUOUehHp8L7lROaVQej_wPt_mPPlk_C2tWAfRj5YYjLLluaeLBsWdxfKiHHEd-PZ7x8UH6Rl91g/s1600/VersionControl2StreamAgile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="91" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCXQnOh8FxZxWkDbxLG1Y1EA55l_zlhbPBHqDzx6HIm9gbJW1Y5IyTuR3T2LsoMzm_XUOUehHp8L7lROaVQej_wPt_mPPlk_C2tWAfRj5YYjLLluaeLBsWdxfKiHHEd-PZ7x8UH6Rl91g/s400/VersionControl2StreamAgile.png" width="400" /></a></div>
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 7. Dual Streams</span></b></div>
<br />
This is very different from traditional version control where branches are eventually discarded (after possibly having been merged back into the trunk) - instead you have two on-going streams. This approach is only possible with a version control system such as Git where a version (ie, a node in the diagrams) can have two parents - in the diagrams this is any node with two outgoing arrows.<br />
<br />
For a large project with multiple teams I have even seen the suggestion of multiple on-going "development" branches (eg: see<span style="color: blue;"> <a href="https://www.infoq.com/articles/agile-version-control" target="_blank">Version Control for Multiple Agile Teams</a></span>). I have not tried this but I have reservations because code merges between the teams would occur irregularly and might easily be forgotten (remember the rule of <b><i>merge early and often</i></b>). The two teams might create conflicting changes which are not discovered until the conflicting code is merged from the trunk into the other teams stream.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUvQIMBHR2QrztSliSi-PtlOMxoZUwIRZdUK2n0cBwMVO6DQOtPvbR0eG0EBpnT_vWqLRiPNgJkBaZawgNRySh5cl8qsn3bIIuh6Mrq9YFZ-_2P3RVFi0Kdatg2AGui-DY7UgreMhkhiw/s1600/VersionControl3StreamAgile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUvQIMBHR2QrztSliSi-PtlOMxoZUwIRZdUK2n0cBwMVO6DQOtPvbR0eG0EBpnT_vWqLRiPNgJkBaZawgNRySh5cl8qsn3bIIuh6Mrq9YFZ-_2P3RVFi0Kdatg2AGui-DY7UgreMhkhiw/s400/VersionControl3StreamAgile.png" width="400" /></a></div>
<br />
<div style="text-align: center;">
<b><span style="font-size: x-small;">Diagram 8. Multiple Development Streams</span></b></div>
<div style="text-align: center;">
<br /></div>
<b><span style="color: #3d85c6; font-size: large;">Summary</span></b><br />
<br />
Agile version control is very different to traditional version control. It is performed using many small feature branches which are being continually merged back into the trunk (or main development stream). This is necessary for the practice of <b>Continuous Integration</b> (CI) which is a core part of the Agile approach.<br />
<br />
CI is an example of <a href="http://devmethodologies.blogspot.com.au/2014/04/jit.html" target="_blank"><span style="color: blue;">JIT</span></a> (and hence <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a>) allowing problems to be found as soon as possible. It also supports other Agile practices such as short sprints and evolving the software using small, simple, user-centric User Stories. Use of CI depends on a version control system that allows easy branching and merging.<br />
<br />
Most Agile teams also have two ongoing code streams (see<b><span style="font-size: x-small;"> Diagram 7</span></b>) - the development "branch(es)" and the delivery "trunk". Again, this relies on a version control system that supports easy merging.<br />
<br />
As far as I know Git is the only version control system currently available where a version node in the repository can have two parents. In other words Git allows you to automatically and safely merge code from different sources.<br />
<br />
Although Git is not without it's problems (which I will discuss next month) I think using it is essential for Agile development to work smoothly. I will discuss the day-to-day use of different version controls systems (including Git) next month.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com3tag:blogger.com,1999:blog-7237530825191390698.post-64993194891073755772015-09-01T00:02:00.001+10:002015-09-02T01:33:20.595+10:00Written vs Verbal<div align="left" style="orphans: 2; widows: 2;">
<span style="color: #3d85c6; font-family: Tahoma; font-size: large;"><b>Introduction</b></span><br />
<br />
Communication of technical information between software developers is crucial. The debate about the advantages and disadvantages of written vs verbal communication has been going on for at least half a century, but even half that time ago, thorough written documentation was generally considered essential. For example, the SEI (Software Engineering Institute) released the <b><i><a href="https://en.wikipedia.org/wiki/Capability_Maturity_Model" target="_blank">CMM</a></i></b> (Capability Maturity Model) around 1990 which heavily emphasized documentation of the product (as well as the procedures used to create the product).<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<div style="text-align: center;">
<b style="font-size: small;">Quality Standards </b></div>
<span style="font-size: x-small;"><br />I did a post-graduate diploma in SQA at UTS in 1993. Much of the software quality stuff was really useful (and found its way into Agile).<br /><br />However, I found CMM and quality standards (like ISO 9001, etc) not that useful if not downright burdensome. They seem to me like a money-making scheme for certification organizations and consultants.
</span></div>
The debate usually centers around requirement specifications or <b><i>specs</i></b>. I have talked about the problems of writing detailed up-front specs before so I won't go into that again (see <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank"><span style="color: blue;">Agile Design</span></a>). [However, in brief specs are incorrect, incomplete, inconsistent, out of date and just generally difficult to understand and use - this is almost inevitable, no matter how hard you try to get them right and maintain them.]<br />
<br />
Agile reopened this debate. One of the five core principles of the Agile Manifesto is to <b><span style="color: #990000;">Favor working code over documentation</span></b>. This is taken by many people to mean that Agile has no place for written documentation. This is not true - Agile does not try to do away with documentation when it is demonstrably useful to the developers and it cannot be replaced with more effective alternatives. (There are often better alternatives, usually in the form of code, of which my favorite is Unit Tests).<br />
<br />
<span style="color: #3d85c6; font-family: Tahoma; font-size: large;"><b>
Written vs Verbal</b></span><br />
<br />
We will start with a recap of what I believe is common knowledge.<br />
<br />
Written documentation is good for well-understood information that needs to be disseminated to different people, and/or at different times. Moreover, the readers (and the writers) can go at their own pace. Another advantage is that the author(s) have the opportunity to fix and refine the document and others can validate it.<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="font-size: x-small;">* The problem of misunderstanding written words has resulted in many problems due to hastily written emails. Often something written as a joke is taken seriously.</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">This is the reason that emoticons (like :) were invented, and why you should carefully read emails, and think about how they may be interpreted, before sending.</span></div>
Verbal communication is good where the actual subject matter is less well-defined or understood, and/or there is a need for interaction between the participants. A commonly cited advantage is that there is often less misunderstanding due to secondary information being conveyed beyond the actual words spoken* - intonation, body language etc.<br />
<br />
On the other hand, studies show that verbal communication is much less likely to be remembered. Further, many work environments have other effects that can interfere with verbal communication such as different accents, background noise, and simply the emotions and distractions of interpersonal communication.<br />
<br />
Apart from these well-known attributes, here are a few more points from my own observations. <br />
<ol>
<li>In my experience some people are good at learning verbally, but many are not. The best approach depends on the team and should allow for personal preferences and abilities. If you favor one approach or the other you may drive away good people.<br /> </li>
<li>In a top-down, autocratic environment people are scared to make a mistake. Verbal communication does not work well since someone will not ask for clarification for fear of appearing stupid. They may also not want to repeatedly ask for clarification for fear of embarrassing the explainer.<br /> </li>
<li>In the software industry (at least in my experience) there are professionals from many different backgrounds. Verbal communication can be problematic when people of different NESBs (non-English speaking backgrounds) attempt to communicate. Written communication can often avoid this problem.<br /> </li>
<li>Written documentation is often used more for self-protection than in any valid attempt to communicate information. (See the case study below.)<br /> </li>
<li>Finally, and possibly most importantly, the documentation produced by a team is typically written by one (or perhaps two or three) people. Other team members have no ownership, and are disinclined to modify or even use the documentation.</li>
</ol>
<ol>
</ol>
<br />
<span style="color: #3d85c6; font-family: Tahoma; font-size: large;"><b>
Document Types</b></span><br />
<br />
We talked briefly about "specs" above but we should clarify the different types of documents typically required for a software project. Traditionally, there are three main documents. (There may also be ancillary documents, such as project plans, test plans, etc.) I will later describe how these documents are used (or avoided) in an Agile environment.<br />
<ol>
<li>User Manual - how to use the software</li>
<li>Specifications - what the software does</li>
<li>Design Document - how it does it</li>
</ol>
There are variations and combinations of the above but these are the three essentials. Note that I won't talk about the User Manual (as this discussion is limited to technical documentation) except to say that one variation is to use the User Manual in place of the specs - that is, first write a detailed User Manual and use that to specify what the software is to do. (In my opinion, this is just as bad an idea as writing detailed up-front specs - I just mention it for completeness.)<br />
<br />
<span style="color: #3d85c6; font-family: Tahoma;"><b>
Technical Documents</b></span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif;">
In CMM jargon:<br />specs == "Software Specifications"<br />design == "Technical Specification"</span></div>
The "technical" documents are the specs and the design. You may know them by other names. For example, the specs are sometimes called the functional specification, customer requirements, etc. What I call the design document may be called the internal design, software architecture, technical design document, etc. Traditionally an analyst writes the former and a designer creates the latter - but these are often done by the same person (analyst/designer).<br />
<br />
Sometimes these two technical documents are also combined, perhaps intentionally, but more often because the analyst/designer has already formed an opinion of how the software will work internally. The specs become full of implementation details, which can needlessly restrict design choices.<br />
<br /></div>
<div align="left" style="orphans: 2; widows: 2;">
Additional problems arise because technical documents try to serve different purposes. Ostensibly they are to tell the developers what to do, but in practice their main audience is the client. First, they they must be comprehensive and sound authoritative to give the client confidence that the project is on the right track. Another purpose is to protect their writers. (You can tell this sort of document by the large number of exclusions, restrictions, provisos, assumptions, and client responsibilities -- for the writer(s) to later point to, when the client is unhappy -- and by the fact that they have to be "signed off" by a large list of stakeholders.)<br />
<br />
<div style="background-color: #f1f1f1; margin: 6px; padding: 6px;">
<span style="color: #3d85c6;">CASE STUDY</span><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">I was attempting to wean the team off detailed written specifications. It was assumed that the client required detailed specs but we found the client was quite happy to work closely with us to create user stories each accompanied by a few acceptance criteria. This was a revelation and even a relief to most of the developers but I still had one experienced developer who was vehemently opposed. After some discussion I discovered why. Here is his story...</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">My colleague had worked for over a year on a large project which was finally delivered. Apparently, this was <i>not</i> a typical waterfall project but the contract <i>did</i> require a large detailed specification to be signed off by all relevant stakeholders. After almost two years the product was delivered but the client was unhappy. There was a large gap in the design. They argued that it was a major oversight that should have been avoided or at least discovered much earlier. My colleague was the scape-goat for the problem, being responsible for much of the analysis and design. After scrutinizing the design document he was saved by one small sentence which implied that the "gap" was explicitly not covered. Since the client had signed off on the document they were clearly the ones at fault. One small sentence in the specifications (not even written by him) saved my colleague his job!</span></div>
<br />
<b style="color: #3d85c6; font-family: Tahoma;">Design Document</b><br />
<br />
In previous posts I talked extensively about the problems with big up-front <i>specs</i> (see the section called <span style="color: #3d85c6;">Problems of BDUF</span> in <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank"><span style="color: blue;">Agile Design</span></a>). A different problem is that the design document is typically <b>underdone</b>. (This happens even, or especially, in an Agile environment as I discuss later.)<br />
<br />
Most of the projects I have worked on in the last three decades had absolutely no design documents. Some possible reasons were: <br />
<ul>
<li>it simply didn't occur to anyone to document the design </li>
<li>the specs already included much of the design </li>
<li>the developers created the design on the fly and never got around to documenting it </li>
<li>the developers simply found it too hard to put technical details into words </li>
<li>there was nobody willing and/or able to write the document </li>
<li>the developers thought the implemented design was "self-describing" </li>
<li>there was unwillingness to document something that was likely to change </li>
<li>there was unwillingness to write something that would be criticized or simply ignored </li>
<li>management didn't ask for it </li>
</ul>
I have had the good fortune to work with some excellent teams that did document the system architecture. However, even then the document was generally ignored or under-utilized. Reasons for this sort of problem might be that developers: <br />
<ul>
<li>don't know the document exists </li>
<li>can't understand the document </li>
<li>have no incentive to understand it </li>
<li>think it is incorrect (even when it isn't) </li>
<li>believe it is out of date, especially as the original author(s) have left </li>
<li>feel no ownership and so will not update or even read it </li>
</ul>
<br />
<b><span style="color: #3d85c6; font-size: large;"><span style="font-family: Tahoma;">
Agile</span></span></b><br />
<span style="font-family: Tahoma;"><br /></span>
Many Agile proponents take the approach that technical documents should be just sufficient and no more -- I call this MVD (minimum viable documentation). The problem with MVD is you can get away with providing no design document whatsoever, unless there are contractual requirements. MVD is short-sighted as it creates huge maintenance problems down the track, especially once the original developers have left.<br />
<br />
So how should you approach documents in Agile? I will look at it from three different angles: who, when, and what. The nice thing is that all ways of looking at the problem lead to similar conclusions.<br />
<br />
<b><span style="color: #3d85c6;">Who</span></b><br />
<br />
First you need a clear idea of who a document is written for. Technical documents (especially those that need to be "signed off") have more than one audience which muddies their purpose. A simple example is that have a lot of detail (superfluous for developers) intended to ensure testers consider all scenarios.<br />
<br />
However, the main problem with specs is they are primarily intended to make the customer happy. First, the specs must be detailed to give the client confidence that the developers know what they are doing.<br />
<br /></div>
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 220px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">“for the developers,<br />by the developers”</span></div>
<div align="left" style="orphans: 2; widows: 2;">
Just as important though is who is the document written <i><b>by</b></i>. A document is not fully utilized unless the users of the document feel they have ownership of it. (It also makes it much more likely it will be kept up to date.) For the team to have ownership the team needs to write the document. Not just one or two people but <i>all</i> the developers need to contribute.</div>
<div align="left" style="orphans: 2; widows: 2;">
<br />
In summary, you need to be clear on the document's audience and purpose. Technical documents need to be written for the developers, by the developers.<br />
<br />
<b><span style="color: #3d85c6;">When</span></b><br />
<br />
The problem can alternatively be seen as one of timing. As we saw above, the purpose of many documents is mainly to demonstrate to the customer that the team know what they (the customer) wants and know how to give it to them. Hence the document is detailed but all this detail is provided much too early which invariably locks the project into a design, which is invariably not the best design.<br />
<br /></div>
<div align="left" style="orphans: 2; widows: 2;">
In large waterfall projects mountains of documents were often written in the analysis and design phases even before the programmers had joined the project!<br />
<br />
On the other hand real world projects before Agile were typically <i>not</i> done anything like that. Developers had to (and sometimes even wanted to) produce documentation but to avoid having to continually modify it to match the changing design (or have it become out of sync) most teams left writing design documents till the end of the project. Unfortunately this is the time when the team probably has little time and motivation to write it, or those who started to write it had left, etc.<br />
<br />
The Agile approach is one of JIT-design. Design is not done until needed. This is the Goldilocks time to update the documentation - not too early and not too late but <i><b>just in time</b></i>.<br />
<br />
I will note here that this is another classic case of <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a>. The developers should be documenting the design as they build it. Of course, this does not mean updating the document whenever any aspect of the design changes. The code itself is the "true" documentation, but looking at the code is not useful for getting a high-level overview. As I have mentioned many times before Unit Tests are very useful for documenting the behavior of modules and how interfaces are meant to work (see the section on <span style="color: #3d85c6;"><b>Documentation</b></span> in <a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-whats-so-good-about-them.html" target="_blank"><span style="color: blue;">Unit Tests</span></a>). However, at the highest level it is important to update design documentation that reflects major changes, particularly if they are core and not likely to change in the future.<br />
<br />
<b><span style="color: #3d85c6;"> What</span></b></div>
<div align="left" style="orphans: 2; widows: 2;">
<b><br /></b>
<b>So what does Agile documentation contain?</b><br />
<br />
It should always record the current state of the system, not some past state or a future proposal. As I mentioned above, it is owned by the team and updated with the code. The documentation is focused on the customer, as it reflects system changes that are driven by the backlog.<br />
<br />
<b>What does it <i>not</i> contain?</b><br />
<br />
You can tell a document is not "Agile" when it is used to tell people what to do. For example, the traditional specification is written by the analysts/designer to tell the programmers what they are to do. Another clue is that it contains lots of disclaimers and provisos and its main purpose is to gain the client's approval.<br />
<br /></div>
<div align="left" style="orphans: 2; widows: 2;">
The author of this type of document is focused on the document itself (and how it is perceived) rather than the success of the product. In other words, it has to be nicely formatted according to company standards, appear complete and authoritative and signed off by all stakeholders.<br />
<br /></div>
<div align="left" style="orphans: 2; widows: 2;">
<b><span style="color: #3d85c6;">How</span></b><br />
<br />
As a bonus I will give an example of <b>how</b> a design document may be created for an Agile project.</div>
<div align="left" style="orphans: 2; widows: 2;">
<ol>
<li>Initially, the developers gather a few user stories and create a simple first version of the software. There is no design documentation as it is easy enough to understand it by inspecting the code. The team have yet to decouple any parts of the system since it is not yet clear why or how to do so.<br /> </li>
<li>As the system grows it becomes obvious how to (but more importantly necessary to) divide the system into modules. How these modules work is "documented" using a comprehensive set of Unit Tests, not written documentation. However, the team needs to create a brief design document that explains the overall design, in particular why it was necessary to decouple certain areas.<br /> </li>
<li>As the system grows many more modules will be needed. New modules will be added or existing ones split as the need arises. The design document is updated by the team as the actual code is updated. This sort of documentation is invaluable for new people joining the team and even for existing team members as the design becomes more complex.</li>
</ol>
<b><span style="color: #3d85c6;">Code</span></b><br />
<br />
Finally, I should explain the vital role of code in the documentation debate. As the saying goes the best information comes "straight from the horses mouth". In software development the actual operational software is the "horses mouth". To extend the, admittedly poor, analogy Unit Tests might then be the "jockey"; Unit tests are also code which interfaces directly with the "horse".<br />
<br />
More traditional documentation is getting further from the horses mouth. In fact most that I have encountered is akin to an ill-informed tip overheard at the local pub.<br />
<br />
Getting back to the point. You often don't need written documentation since the actual behavior of the software is a better form "documentation". Further, Unit Tests demonstrate how modules can be used, are often easier to understand (and can even be stepped through in the debugger), are typically more comprehensive (especially with regard to error-handling) and are never out of date (if run regularly).<br />
<br />
<div style="background-color: #f1f1f1; margin: 6px; padding: 6px;">
<span style="color: #3d85c6;">OBJECTION</span><br />
<br />
An objection I often get: "I think the software is doing the wrong thing. How can I check if there is no written document describing what it should do?" My reply is: "What do you think it should do? And more importantly, what does the customer think it should do?"<br />
<br />
However, sometimes the customer doesn't care and the behavior is determined by external reasons, such a technical limitations, government regulations, etc. Sometimes UAT (user acceptance test) scripts can document the correct behavior - but UAT scripts have a habit of quickly becoming out of date.<br />
<br />
In many cases this is a valid objection and a good example of why documents are still required.<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">
</span></div>
<br /></div>
<div align="left" style="font-family: Tahoma; orphans: 2; widows: 2;">
<span style="color: #3d85c6; font-size: large;"><b>Conclusion</b></span><br />
<br />
In the past, waterfall methodologies, quality standards (particularly CMM), and simply the influence of how things are done in other "engineering disciplines" have meant that there is far too much emphasis on documentation in the software development process. On the other hand Agile extremists have gone to the other extreme of MVD or even no documentation. The right balance is somewhere in between.<br />
<br />
That said, it's better to err on the side of too little. But I still believe that for a large project some documentation is needed to explain or remember important details that cannot be easily gleaned from the code.</div>
<div align="left" style="font-family: Tahoma; orphans: 2; widows: 2;">
<br />
Some simple rules to remember are:</div>
<div align="left" style="font-family: Tahoma; orphans: 2; widows: 2;">
<ul>
<li>avoid documentation if you can</li>
<li>there are often better alternatives (like Unit Tests)</li>
<li>technical documentation is written for the developers only</li>
<li>practice <b><i>continuous documentation</i></b> - ie, update the doc at the same time as the code</li>
<li><b><i>ownership</i></b> of documents by the team is just as important as content</li>
</ul>
</div>
<div align="left" style="font-family: Tahoma; orphans: 2; widows: 2;">
<br /></div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-64523697307079659392015-04-18T21:29:00.002+10:002015-07-05T23:04:50.806+10:00Team Collaboration<span style="font-family: Times, Times New Roman, serif;">Collaboration is at the core of problems experienced when implementing Scrum (or any team work). As I mentioned last week, consideration of personalities is important when composing a team. This is a big/important enough subject that I decided to devote a whole post to it.<br /><br />Developers, generally, are simply not good at working in a team. In the past, good programmers could get away with working fairly independently in their own specialized area. Nowadays, larger projects, more varied project types and different development methodologies means that good team-work is expected of everyone. It is a simple demonstrable fact that collaborative (Agile) teams invariably produce a better outcome, more efficiently and with less risks.<br />
</span>
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 220px;">
<span style="font-family: Times, Times New Roman, serif;"><span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
“collaborative teams<br />invariably produce<br />a better outcome...”</span></span></div>
<span style="font-family: Times, Times New Roman, serif;">You can try to hire people with the right personality, but it's not necessary (and sometimes you simply don't have that choice). Luckily, using Scrum and some tips that I mention below, most developers can learn to work as part of a team, and even enjoy working with others for a worthwhile goal.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br /></span>
<span style="color: #3d85c6; font-size: large;">Why Teams Don't Collaborate</span><br />
<div>
<br style="font-family: Tahoma; orphans: 2; widows: 2;" />
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">Poor collaboration is most obviously seen in conflict over technical issues. In three decades in the industry I have seen this many times. When you get to the heart of the matter the problem is rarely purely a technical issue but also due to personality conflict, poor communication or interpersonal skills (or even emotional disturbance).</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">Differences of opinion on technical topics such as software design, coding standards, etc are inevitable. Often this is simply a sign that different people have different priorities - eg, different team members may focus on different aspects of the quality of the code such as efficiency vs maintainability. (See <a href="http://devmethodologies.blogspot.com.au/2012/02/importance-of-developer-quality.html" target="_blank"><span style="color: blue;">Importance of Developer Quality Attributes</span></a> for more on software quality attributes and their relative importance.) When the team is collaborating, and pulling in the same direction these issues can disappear, or become much easier to resolve, since team members are more amenable to compromise.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">Managers often realize there is more behind the disagreement, such as a clash of egos. But they fail, or are reluctant to, to dig deep enough to find that some of the team may feel disempowered, threatened or generally dissatisfied. Again, a Scrum team overcomes these sorts of problems by empowering and encouraging communication and collaboration.</span><br />
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;"><br /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;"></span><br />
<b style="font-family: Tahoma; orphans: 2; widows: 2;"><span style="color: #3d85c6; font-family: Times, Times New Roman, serif;">Personality</span></b><br />
<div>
<b style="font-family: Tahoma; orphans: 2; widows: 2;"><span style="color: #3d85c6; font-family: Times, Times New Roman, serif;"><br /></span></b></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJO2nIBk6LGPS1rL_ME6oEvwFO-UQrMefRyjCxP9mccubMTSVOetJd0Tr6rzEAO0noHZ64zwpsh1NzwsyT5wFy7F_Sr9AHLNBwwIAd5PcDu4bSNbXyKxDrd1hxJSy-CLqcRaLh4LUTG0U/s1600/DISCdev.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJO2nIBk6LGPS1rL_ME6oEvwFO-UQrMefRyjCxP9mccubMTSVOetJd0Tr6rzEAO0noHZ64zwpsh1NzwsyT5wFy7F_Sr9AHLNBwwIAd5PcDu4bSNbXyKxDrd1hxJSy-CLqcRaLh4LUTG0U/s1600/DISCdev.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Typical Developer DISC Profile</td></tr>
</tbody></table>
To get an idea of why collaboration does not happen let's look at the personality of a typical developer. Last month I mentioned the DISC system of personality assessment (see <a href="http://devmethodologies.blogspot.com.au/2015/04/scrum-team-composition.html" target="_blank">Team Composition</a>). Developers tend to fall in the S-C-D range and are predominantly of the C personality type (see diagram at right). This means they are conscientious and competent, striving for accuracy and quality. However, they prefer to work independently with little social interaction.<br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">It seems that the software industry tends to attract people who are averse to collaboration. (In fact DISC assessors recommend software development as an appropriate career for those with a C personality type!) This is the major problem when attempting to get a Scrum team to collaborate and self-organize.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">So do we give all new recruits a personality test and only hire developers with the right personality type? <b><i>No</i></b> -- that's not a good idea. It would greatly reduce the pool of potential candidates, some of whom may be otherwise ideally suited to the role. The fact is almost all developers (even the extreme case of someone with Aspergers) can learn to collaborate, and even enjoy working in a small self-organizing team.</span><br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVc4D54QNljfooZ2Rb4WZVV9Z8vOCWFm3_dqJTPi0MVmB3w39LQsRN4bXFAyScBthvzVC3VrMy4Fyn-21mr_UWrsTZBn1QTJQ1oO5p_ym0N_H61q3AbBVol0wNeHr_x6RoJYPwkC0lO-Y/s1600/DISCint.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVc4D54QNljfooZ2Rb4WZVV9Z8vOCWFm3_dqJTPi0MVmB3w39LQsRN4bXFAyScBthvzVC3VrMy4Fyn-21mr_UWrsTZBn1QTJQ1oO5p_ym0N_H61q3AbBVol0wNeHr_x6RoJYPwkC0lO-Y/s1600/DISCint.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My <b>Internal</b> DISC Profile</td></tr>
</tbody></table>
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">I believe this non-collaborative behavior is primarily a conditioned or learnt response, as I explain later. This is clearly shown with DISC personality assessments of a typical developer. DISC assessments give two personality profiles - called internal and external. An internal profile (see diagram at right) reveals a person's natural tendencies, whereas the external profile (see diagram below) shows actual behavior in the work environment. In disempowering environments developers typically suppress their collaborative tendencies.</span><br />
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;"><br /></span>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirUcD3lwWMJ5kqmeeyxjFaD-4WI3E7fhAU33ow7v4hLlDDQUSpxZdDjevHQ-UWSMWEt1FoegBaYUjdWt_VZRvacy6EKv_wsqhitLfmaVh35HI4HvpeP4CIeHmfRFXO9qhh1uBgwQPDyQU/s1600/DISCext.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirUcD3lwWMJ5kqmeeyxjFaD-4WI3E7fhAU33ow7v4hLlDDQUSpxZdDjevHQ-UWSMWEt1FoegBaYUjdWt_VZRvacy6EKv_wsqhitLfmaVh35HI4HvpeP4CIeHmfRFXO9qhh1uBgwQPDyQU/s1600/DISCext.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My <b>External</b> DISC Profile</td></tr>
</tbody></table>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">For example, last year I had a DISC assessment which showed that for my Natural/Internal personality my S and C styles were about average. However, for my Adapted/External personality my S style had disappeared. (The S personality type is supportive and likes working closely with other people.)</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif;"><span style="font-family: Tahoma; orphans: 2; widows: 2;">What was it that suppressed my natural collaborative tendencies? I think there are a number of factors which I cover in the next few sections. </span><span style="font-family: Tahoma; orphans: 2; widows: 2;">Further, I also believe that proclivity to working in a small team is a part of human nature as I explain later in the section below entitled <b><span style="color: #3d85c6;">Homo Habilis</span></b>.</span></span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<b style="font-family: Tahoma; orphans: 2; widows: 2;"><span style="color: #3d85c6; font-family: Times, Times New Roman, serif;">Training</span></b><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">Training in the industry tends to reinforce the notion that software development (at least design and coding) is a solitary activity. For example, in all the courses I did at uni. just one (of the dozens) of modules I took involved working as part of a team - my 3rd year course on "Software Engineering". Things have undoubtedly improved since 1983 but I still believe there is a problem.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<b style="font-family: Tahoma; orphans: 2; widows: 2;"><span style="color: #3d85c6; font-family: Times, Times New Roman, serif;">Conditioning</span></b><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">Even more significant is non-collaborative behavior that is reinforced by many organization's culture or managerial practices. Many managers, by their attitude and behavior, promote rivalry and even conflict between team members. This is symptomatic of a command-and-control management style as I discussed previously (see <a href="http://devmethodologies.blogspot.com.au/2014/12/production-line-mentality-and-silo.html" target="_blank"><span style="color: blue;">Production Line Mentality</span></a>).</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">Managers often realize that what they do and say has detrimental effects and try to change their behavior. However, this can be difficult when motives are questioned. For example, common advice is "Praise publicly, criticize privately" - but this can backfire. Of course, you should never criticize publicly - it is demoralizing and humiliating - but (too much) public praise may not be seen as genuine and may trigger envy in other team members. A sudden change in behavior will also be viewed with suspicion unless there is evidence of a change of attitude. Above all never say one thing and do another.</span><br />
<br style="font-family: Tahoma; orphans: 2; widows: 2;" />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<div style="text-align: center;">
<span style="font-family: Tahoma; orphans: 2; widows: 2;"><b>Praise privately </b></span></div>
<br style="font-family: Tahoma; orphans: 2; widows: 2;" />
<span style="font-family: Tahoma; font-size: xx-small; orphans: 2; widows: 2;">It's commonly said to "criticize privately but praise publicly". My own policy is to give all feedback to employees privately - both criticism and praise.</span><br />
<span style="font-family: Tahoma; font-size: xx-small; orphans: 2; widows: 2;"><br /></span>
<span style="font-family: Tahoma; font-size: xx-small; orphans: 2; widows: 2;">Of course (unless you are very good a deception :) it should also be honest, otherwise it is simply seen as manipulative.</span><br />
<span style="font-family: Tahoma; font-size: xx-small; orphans: 2; widows: 2;"><br /></span>
<span style="font-family: Tahoma; font-size: xx-small; orphans: 2; widows: 2;">Admittedly, it is nice to ensure it is known publicly when someone has done a good job.</span></div>
<span style="font-family: Times, Times New Roman, serif;">In addition, many companies have policies that work against team work. For example, such things as Annual Performance Reviews and Employee of the Month awards usually have little effect apart from causing resentment. But when they do have an effect it is one that promotes competition and rivalry which actually undermines collaboration.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br /></span>
<span style="color: #3d85c6; font-size: large;">Why Teams Should Collaborate</span><br />
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;"><br /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">We have seen how the personality, training and years of conditioning make it difficult for developers to work together - so why don't we give up on the idea of an highly-collaborative, self-organizing team?</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;"><b><span style="color: #990000;">Don't give up!</span></b> If we can overcome the above problems then there are big advantages. I have been expounding these advantages (and the disadvantages of a command-and-control no-collaborative approach) in all my posts since last December (except for <b><span style="color: #3d85c6;">Lean is Not Agile</span></b>).</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">In summary they are:</span><br />
<ul>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">more creative ideas are generated</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">less coordination overhead</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">avoids many pointless activities</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">greater focus on giving the customer what they need</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">less specialization leading to greater productivity</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">specialists cannot hold the organization to ransom</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">greater adaptability to change</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">greater job satisfaction</span></li>
<li><span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">greater productivity</span></li>
</ul>
<span style="font-family: Times, Times New Roman, serif; orphans: 2; widows: 2;">In essence a good Scrum team will produce better results. Further, the results are often produced more quickly - or there is, at least, the perception of increased productivity because the team is focused on what is important to the customer - in the short term. In the long term there are definitely large productivity benefits.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br style="font-family: Tahoma; orphans: 2; widows: 2;" /></span>
<b style="font-family: Tahoma; orphans: 2; widows: 2;"><span style="color: #3d85c6; font-family: Times, Times New Roman, serif;">Disadvantages</span></b><br />
<br />
In researching this post I found quite a few web pages arguing against small self-managing teams (eg: <a href="https://softwaremaestro.wordpress.com/2007/07/02/does-xpscrum-violate-the-agile-manifesto/" target="_blank">Does XP/Scrum Violate the “Agile Manifesto”?</a>), Some of them have a point, but some are simply incorrect. I refined it to six basic points which I will now address.<br />
<br />
<span style="color: #3d85c6;"> 1. Having many small tasks done by different people results in inconsistencies.</span><br />
<br />
This will happen in any team, but in Scrum team members are actually more likely to work together to avoid these sorts of problems. For example, in almost all jobs I have had there have been coding standards "in use", but I have only ever seen them followed with any rigor in a Scrum team.<br />
<br />
<span style="color: #3d85c6;">2. Group decisions are often not good decisions.</span><br />
<br />
The team may be prone to "group think", but this is not due to Scrum. In fact, Scrum empowers individuals to make a contribution. The focus should be on finding the best solution, <b>not</b> going along with everyone else.<br />
<br />
There will be occasions where there are differences of opinion on technical issues, but in my experience, when all team members are aligned, these are easy to resolve. Moreover, decisions are often not group decisions since generally Scrum teams have experts in different areas to whom they defer.<br />
<br />
<span style="color: #3d85c6;">3. Decisions are slow because they are made by committee.</span><br />
<br />
First, it is important to remember that a Scrum team is not a committee. Most committees are composed of members with very different agendas; whereas in a Scrum team all members should have the same focus.<br />
<br />
Also, it may appear that a team is indecisive because they are using an important Agile practice of deferring decisions until necessary (see <a href="http://devmethodologies.blogspot.com.au/2014/04/jit.html">JIT</a>). When the current backlog task dictates that a decision be made then a good Scrum team will not hesitate to decide (or give it to the expert in that area to decide).<br />
<br />
<span style="color: #3d85c6;">4. There is no single person with the authority to enforce design consistency.</span><br />
<br />
This is related to the previous points. The argument is that there is nobody in control who sees the big picture, which results in haphazard decisions and inconsistencies in the design. Common opinion is that it's better to have a single person with the vision to direct the project.<br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
“Scrum...works better<br />than the single<br />visionary approach”</span></div>
The truth is that the "single visionary" approach does not work well with a team of more than a few people. The people actually creating the software are continually twisting and changing the vision for many reasons. The visionary is flat out ensuring that her vision is implemented.<br />
<br />
Scrum encourages a better approach where <i>everyone</i> sees, or at least has a grasp of, the big picture. It does not always work perfectly, but it works better than the single visionary approach.<br />
<br />
<span style="color: #3d85c6;">5. The more you divide a task between people the greater the communication burden.</span><br />
<br />
Again, this is simply a consequence of working in a team of more than a few people. Using Scrum and feature teams (an example of <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a>) actually reduces the communication burden.<br />
<br />
<span style="color: #3d85c6;"> 6. There is no individual ownership and pride in work.</span><br />
<br />
I talked about this<span style="color: blue;"> <a href="http://devmethodologies.blogspot.com.au/2015/04/scrum-team-composition.html">last week</a></span> (see the section on <span style="color: #3d85c6;">Code Ownership</span>). You may believe, as I do, that you write perfect code, but with input from other team members it can be even better. Moreover, there are other disadvantages of ownership such as specialization, increased risk, etc.<br />
<br />
Of course, taking pride in your work is a good thing. Knowing you have done a good job is immensely satisfying. What I didn't expect with Scrum is that I can be even more proud when my <i>team</i> does a good job.<br />
<br />
<b><span style="color: #3d85c6;">Homo Habilis</span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG1lJ8cfkqONZg5exKvteVIsEiN-pJ-TM_o2w8ON6uQtRLYI57d94NF95HVtSABB6TNG8pbbRlzb3gOOld8kV8WP_O-V1_cCVAi5WQRY2cbUM5Vrm8f_pXk4I6W4isUtGsIphQWUgKNQE/s1600/HomoHabilis.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Times, Times New Roman, serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG1lJ8cfkqONZg5exKvteVIsEiN-pJ-TM_o2w8ON6uQtRLYI57d94NF95HVtSABB6TNG8pbbRlzb3gOOld8kV8WP_O-V1_cCVAi5WQRY2cbUM5Vrm8f_pXk4I6W4isUtGsIphQWUgKNQE/s1600/HomoHabilis.jpg" /></span></a></div>
<div>
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span>
<span style="font-family: Times, 'Times New Roman', serif;">One fundamental advantage that humans have is the ability to work in small teams. Humans are inherently social - far more than any other species. Much of this behavior (or tendency towards the behavior) is built into our DNA, due to our recent evolution over the last few hundred thousand or more years.</span><br />
<span style="border-collapse: separate; border-spacing: 0px; font-family: Times, Times New Roman, serif; orphans: 2; text-align: -webkit-auto; widows: 2;">
</span></div>
<div>
<span style="border-collapse: separate; border-spacing: 0px; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="font-family: Times, Times New Roman, serif;"><br />
The formation of small teams was an important early step in human evolution probably beginning more than two million years ago when Homo Habilis began hunting in small self-organizing teams.<br /><br />
Many developers work for years, even decades, almost in isolation, which can be alienating. Many report having an immense feeling of satisfaction when they first work on a collaborative, high-performance Scrum Team. The problem is that not all teams are like that - in the next section we will try to fix that.</span><br /><br /><span style="color: #3d85c6; font-family: Tahoma; font-size: large;">
How to Encourage Collaboration</span><br /><br /><span style="font-family: Times, Times New Roman, serif;">
Collaboration is fundamental to Agile and Scrum in particular. Lack of a collaborative spirit is usually the reason that Scrum fails. So how do we fix it?<br /><br /><b><span style="color: #3d85c6;">
Scrum Practices</span></b><br /><br />
Scrum practices encourage collaboration. The visibility provided by the daily standup provides a feedback mechanism that keeps everyone on the same track (as well as providing motivation and peer pressure - see the discussion of the Ringelmann Effect in <a href="http://devmethodologies.blogspot.com.au/2015/02/scrum-communism.html" target="_blank"><span style="color: blue;">Scrum == Communism</span></a>). The product owner, and particularly their product backlog, keeps everyone focused on the one thing - what the customer needs. Empowering the team gets them working together to come up with creative solutions.<br /><br /><b><span style="color: #3d85c6;">XP Practices</span></b><br /><br />Other Agile (not specifically Scrum) practices also help. Here are some examples from XP.<br /><br />
A common open work area for the team encourages communication. (See <a href="http://www.extremeprogramming.org/rules/space.html" target="_blank"><span style="color: blue;">XP:Space</span></a>)<br /><br />
A customer representative (eg, the PO in Scrum) works closely with the team. This not only allows the developers to obtain timely help, it also gives the customer invaluable insight into the development process as I explained in <span style="color: blue;"><a href="http://devmethodologies.blogspot.com.au/2013/09/customer-management.html" target="_blank"><span style="color: blue;">Customer Management</span></a>. </span>(See <a href="http://www.extremeprogramming.org/rules/customer.html" target="_blank"><span style="color: blue;">XP:Customer</span></a>)<br /><br />
Continuous integration means the developers are always working together to ensure that the system works and that code modifications are compatible. (See <a href="http://www.extremeprogramming.org/rules/integrateoften.html" target="_blank"><span style="color: blue;">XP:CI</span></a>)<br /><br />
One of the best signs of a good team is when programmers are happy to work on other's code and have other's modify their code. At the very least all code should be reviewed by at least one other person. If people get defensive about "their" code then that is a problem. Pair programming is the ultimate aim in this regard, and has the added benefit of producing better code. (see <a href="http://www.extremeprogramming.org/rules/pair.html" target="_blank"><span style="color: blue;">XP:Pair</span></a>)<br /><br />
Related to pair programming is the idea of "collective code ownership". Nobody owns any piece of the code (or anything at all, actually), so anyone is free to modify any part of the code. Note that I do agree that often only the original creator(s) of a piece of code may be the only one to appreciate all nuances of the code, which is why <a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-whats-so-good-about-them.html" target="_blank"><span style="color: blue;">Unit Tests</span></a> are essential to ensure that changes do not introduce bugs. (See <a href="http://www.extremeprogramming.org/rules/collective.html" target="_blank"><span style="color: blue;">XP:Ownership</span></a>)<br /><br /><b><span style="color: #3d85c6;">
Enhancing Team Spirit</span></b><br /><br />
Unfortunately, some teams just never "click". Usually the problem is the "mind-set" of one or more team members, as I discuss below. First we look at building team spirit which can be the first step towards changing a mind-set.<br /><br />
Here are 12 suggestions:</span></span><br />
<ol><span style="border-collapse: separate; border-spacing: 0px; font-family: Times, Times New Roman, serif; orphans: 2; text-align: -webkit-auto; widows: 2;">
<li><span style="text-align: -webkit-auto;">encourage open and honest communication</span></li>
<li><span style="text-align: -webkit-auto;">empower the team to make decisions</span></li>
<li><span style="text-align: -webkit-auto;">communicate about strategic planning/goals</span></li>
<li><span style="text-align: -webkit-auto;">encourage team members to trust each other</span></li>
<li><span style="text-align: -webkit-auto;">make the most of the talents of the team</span></li>
<li><span style="text-align: -webkit-auto;">never punish or humiliate team members for mistakes</span></li>
<li><span style="text-align: -webkit-auto;">avoid behavior (like public criticism/praise) which promotes rivalry</span></li>
<li><span style="text-align: -webkit-auto;">never compare team members against each other</span></li>
<li><span style="text-align: -webkit-auto;">reward the team not individual team members</span></li>
<li><span style="text-align: -webkit-auto;">encourage the team to be polite to each other</span></li>
<li><span style="text-align: -webkit-auto;">encourage the team to eat together</span></li>
<li><span style="text-align: -webkit-auto;">encourage the team to see the customer's point of view</span></li>
</span></ol>
<span style="border-collapse: separate; border-spacing: 0px; font-family: Times, Times New Roman, serif; orphans: 2; text-align: -webkit-auto; widows: 2;">
<b><span style="color: #3d85c6;">Changing Mind Set</span></b><br /><br />
I guess the whole point of this post is that many developers have the wrong mind-set. They become defensive when their mistakes are pointed out. Alternatively they are reluctant to give feedback when someone does a bad job for fear of offending them or getting a bad reaction. People <i>forget</i> to give positive feedback when someone does a good job.<br /><br />
Somehow you need to encourage the team to be open and honest with each other. A collaborative environment where people bounce ideas off each other will produce the best possible software.<br /><br />
Here are 12 tips for team members:</span><br />
<ol><span style="border-collapse: separate; border-spacing: 0px; font-family: Times, Times New Roman, serif; orphans: 2; text-align: -webkit-auto; widows: 2;">
<li><span style="text-align: -webkit-auto;">trust team-mates to do their job</span></li>
<li><span style="text-align: -webkit-auto;">be open to new or different ideas</span></li>
<li><span style="text-align: -webkit-auto;">take responsibility for committed tasks</span></li>
<li><span style="text-align: -webkit-auto;">always find a way to make a contribution</span></li>
<li><span style="text-align: -webkit-auto;">be open to helping in areas outside your expertise</span></li>
<li><span style="text-align: -webkit-auto;">look at things from the customer viewpoint</span></li>
<li><span style="text-align: -webkit-auto;">don't be defensive when someone points out a mistake or a better way</span></li>
<li><span style="text-align: -webkit-auto;">don't hide your mistakes</span></li>
<li><span style="text-align: -webkit-auto;">don't be afraid to give negative feedback BUT</span></li>
<li><span style="text-align: -webkit-auto;">don't be offensive in pointing out other people's mistakes</span></li>
<li><span style="text-align: -webkit-auto;">be polite and respectful</span></li>
<li><span style="text-align: -webkit-auto;">never put personal ambition ahead of the project</span></li>
</span></ol>
<span style="border-collapse: separate; border-spacing: 0px; font-family: Times, Times New Roman, serif; orphans: 2; text-align: -webkit-auto; widows: 2;">
<b><span style="color: #3d85c6;">Culture</span></b><br /><br />
As I discussed a few years ago (see <a href="http://devmethodologies.blogspot.com.au/2013/01/why-scrum-fails.html" target="_blank"><span style="color: blue;">Why Scrum Fails</span></a>) the root cause of the failure of Scrum is the culture of the organization. The team will not change their mind-set if the culture discourages it.<br /><br />
First, managers need to relinquish their control, so the team can effectively self-organize. Rewards should encourage collaboration - ie, team rewards, not individual bonuses. Encourage the team to identify and fix their own problems.<br /><br />
Most importantly, it is important to drive out fear. People won't take risks if they are fearful of the repercussions when things don't go to plan.</span><br />
<span style="border-collapse: separate; border-spacing: 0px; font-family: Times, Times New Roman, serif; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span><span style="color: #3d85c6; font-size: large;">Conclusion</span></div>
<span style="font-family: Times, Times New Roman, serif;"><br />Scrum is centered around the team - a small, stable, self-organizing, self-managing, collaborative team. When the team works well together Scrum works very well. When the team does not collaborate Scrum does not work well.<br /><br /> Unfortunately, many developers by their nature are not prone to collaborative behavior. Luckily this is not an inherent limitation but is a mainly a conditioned response due to years of working in an oppressive environment.<br /><br />The advantages of removing an untrusting, blaming culture and overcoming developers defensiveness to develop a collaborative team are big. As explained above there are many benefits but in essence better results are produced, often more efficiently and with greater satisfaction to customer and developers.<br /><br />Many of the practices of Scrum help to encourage collaboration such as the visibility provided by the daily standup and the focus provided by the backlog. Feature teams as discussed last week are also important. Further, other Agile practices such as continuous integration, collective code ownership, customer focus, collocation, etc are very useful.<br /><br />The most important thing is to change the environment to one where the developers are empowered to do their best and rewards are team-based not individual.<br /><br />Further, developers need to be open to the change and fight their defensiveness and preference for working alone. It may be surprising that working as part of a highly-functional small team can be deeply satisfying.</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br /></span>Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com3tag:blogger.com,1999:blog-7237530825191390698.post-22135735215826158362015-04-03T21:17:00.002+11:002015-04-21T18:58:40.176+10:00Scrum Team Composition<div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Last week we saw how important it was to get the size of a Scrum team right. This time I will look at another issue that is just as important - team composition or who to put on which team.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Of course, if you only have enough people for a single team this blog may not be relevant to you. However, there are things of interest such as a look at personalities of team members and how that affects collaboration. [Late note: I have split off the bit about collaboration into my next post, so I only cover it briefly here.]</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="color: #3d85c6; font-size: large;">Personalities</span></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The biggest problem I have found with the successful adoption of Scrum is team members who seem incapable of working effectively together. This can mostly be put down to personalities. First, different people sometimes just don't get along, for no obvious reason. This is why a bit of consultation, judgement and experimentation may be required when composing teams.</span><br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif8mjos0vJCTnEQ0uLYCYgXTCZtlOmOyT097I_YztXodEHYDs2t_KFzsJ482ZorU1rd1aI2MdX46qKHZpcdRRRysBJi-NkqnmKV-cRafKGDpJYtAwDNRq7pWpHgwBYkULyCc-tceGHMhU/s1600/DISCdev.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif8mjos0vJCTnEQ0uLYCYgXTCZtlOmOyT097I_YztXodEHYDs2t_KFzsJ482ZorU1rd1aI2MdX46qKHZpcdRRRysBJi-NkqnmKV-cRafKGDpJYtAwDNRq7pWpHgwBYkULyCc-tceGHMhU/s1600/DISCdev.png" height="158" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Typical developer personality profile</b><br />
(provided by <a href="http://discpersonalitytesting.com/" target="_blank">DISC Personality Testing</a>)</td></tr>
</tbody></table>
More significant is that most developers generally have a personality type that rails against the collaboration inherent in Agile methodologies. If you are familiar with the DISC system of personality classification and assessment you may already be aware that software professionals are generally of the S personality type something like in the diagram. Importantly, for our discussion, it means they prefer to work alone. (However, I believe this is, at least partially, a learnt or conditioned behavior, as I discuss next week.)<br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">This causes the sorts of problems you have probably seen, such as continual disagreement about approaches to technical problems. Less obvious is the developer who is uncooperative with Scrum practices or other areas of their work that they are unhappy with - they may be ostensibly open and helpful, and may not even be aware of their behavior and how it causes problems. Most important is how personality affects collaboration between team members.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Many companies adopting Scrum attempt to hire developers of the desired personality. This is why a lot of job ads emphasize the "team player" aspect. Some companies go as far as performing personality testing (such as DISC) on job candidates. I think this is the wrong approach as most developers can be encouraged to be collaborative given the right environment which I discuss next week.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="color: #3d85c6; font-size: large;">Team Structure</span></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">I already talked about the different skills required (and <i>not</i> required) in an Agile development environment - see <a href="http://devmethodologies.blogspot.com.au/2014/12/agile-roles.html" target="_blank"><span style="color: blue;">Agile Roles</span></a>. What I did not cover is how to structure the teams, basically which people to put together in the same team. The basic rule is that you need <span style="color: #990000;"><b>all the skills in a team required to complete the tasks in the backlog of that team</b></span>. I will elaborate on this below but first we look at why it is important.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Coordination</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">A major consideration when composing teams is to reduce the costs of communication by putting those people on the same team that need to work closely together. </span><br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 280px;">
<div style="text-align: center;">
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="color: #0b5394; font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Component vs Feature Teams </b></span></span></div>
<span style="color: #0b5394;"><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" /></span>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">In <b><i>Succeeding with Agile,</i></b> Mike Cohn calls teams structured around the architectural design of the software <b><i>Component Teams</i></b>. He contrasts this with teams structured according to customer requirements which he calls <b><i>Feature Teams</i></b>.<br /><br />See <i>Succeeding with Agile</i> [ISBN-13: 978-0-321-57936-2] pages 183-188.</span></span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
The simplistic way to do this is to group people working on the same sorts of things - so you might have an analysis team, an architecture team, coding, testing, installation and support teams, etc.</span><br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The developers too are split into sub-teams based on different parts of the software they work on, Examples I have seen are a database team, services layer team, display engine, AI, comms, backend server, web interface, etc. In Agile jargon these are called <b><i>Component Teams</i></b> (see note at right).</span><br />
<br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><i>Component Teams</i> do not work well in an Agile environment, as we will see, but even in a traditional non-Agile project they cause problems like:</span><br />
<ul>
<li>silo syndrome (see <a href="http://devmethodologies.blogspot.com.au/2014/12/production-line-mentality-and-silo.html" target="_blank"><span style="color: blue;">Production Line Mentality</span></a>)</li>
<li>unnecessarily complex designs (see below)</li>
<li>contorted designs due to changes made in the wrong place</li>
<li>modules with unneeded features due to perceived future needs</li>
<li>over-specialization</li>
<li>uneven workload</li>
<li>dependence on multiple teams to meet a deadline</li>
<li>code ownership problems (see below)</li>
<li>narrow focus on a specific task/module</li>
<li>lack of focus on delivering what the customer wants</li>
<li>isolating people who often need to communicate</li>
<li>need for lots of "interface" documentation</li>
<li>a lot of integration testing work</li>
<li>requires a lot more planning</li>
</ul>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">An alternative is to be customer-oriented when composing teams. Each team can focus on one or more aspects of delivering something useful to the customer - ie, <b><i>Feature Teams</i></b>. Feature teams are focused on completing tasks on the product backlog. Typically these would be about different aspects of the user-interface, but other things may be important to the customer, such as data-compatibility with their systems.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Software Design</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Talking about software design may seem completely off topic here, but the design of a piece of software is closely linked to how the people creating it interact. Some say that <b><span style="color: #990000;">organizational structure determines software architecture</span></b>. It could be the other way around. In either case it is important for those involved in the system architecture to also be involved in the creation of the teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Interestingly, this relationship might also explain why the <a href="http://devmethodologies.blogspot.com.au/2012/10/the-layer-anti-pattern.html" target="_blank"><span style="color: blue;">Layer Anti-pattern</span></a> is so common. I have noticed the tendency of organizations with many layers of management to also develop software with lots of layers. The Layer Anti-pattern demonstrates poor or unnecessary separation of concerns which interferes with the ability of modules to communicate and adds to the complexity of the software. Analogously, a layered organizational structure interferes with collaboration. Both are examples of how a simplistic layered approach can work against the <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE</a>.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">DIRE</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">This whole discussion can also benefit from a consideration of the DIRE principle. Conventional thinking is that people doing the same things should be on the same team - a <b><i>Component Team</i></b>. Using the DIRE principle we compose teams in such a way that people who need to work closely together are on the same team. (In this case the team members are the "related entities" - see <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE</a> for more info.)</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Further, this is a result of the Agile emphasis is on delivering useful features to the customer, by performing the tasks for a particular feature at once (or as close in time as possible). This is also an example of DIRE - in this case DIRE stands for "Don't Isolate Related Events".</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="color: #3d85c6; font-size: large;">Component Teams</span></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Before we look at feature teams in detail let's cover how component teams work. Many of the deficiencies of component teams are due to developers employing "silo" thinking. See <a href="http://devmethodologies.blogspot.com.au/2014/12/production-line-mentality-and-silo.html" target="_blank">Production Line Mentality and Silo Syndrome</a> for more on this -- but here I just discuss problems specific to software development.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Note that even teams that deal directly with the user interface may still be component teams. For example, the "GUI" team in the diagram below is a component team (as, of course, are the other two teams) since the development of most features would typically involve at least one other team.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZtHtp-GcYTkhNgb2lIpe7koFe5tt717iiNeEImG_XP8Pq2Jc0fxcVkelboQD3r9tvmnmug3qll60S18HVwHq5a2JjuoEbz4Qo6D69GZeX8MTu0Nt8sNB1hi7uF3zfD4fpiX9CjJ5NxMI/s1600/Component+Teams.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZtHtp-GcYTkhNgb2lIpe7koFe5tt717iiNeEImG_XP8Pq2Jc0fxcVkelboQD3r9tvmnmug3qll60S18HVwHq5a2JjuoEbz4Qo6D69GZeX8MTu0Nt8sNB1hi7uF3zfD4fpiX9CjJ5NxMI/s1600/Component+Teams.png" height="206" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Component Teams</b></td></tr>
</tbody></table>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">In the following discussion I will discuss a theoretical component team with one or more dependent teams -- such as the Math Team in the diagram, which has the Services Team and the "GUI" team as dependent teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Complexity</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Using component teams tends to lead a project towards the dark side called BDUF (big design up front), which I hope you are aware is very bad and the antithesis of the Agile approach -- if not see <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">Agile Design</a>. Components developed like this are always overly complex, with many unneeded facilities. This makes the code harder to understand, harder to verify, and makes it less amenable to modifications. In my experience, the worst thing is that it's harder for the users of the component (ie, dependent teams) to understand how to use it (see <a href="http://devmethodologies.blogspot.com.au/2013/12/the-gas-factory-anti-pattern.html" target="_blank"><span style="color: blue;">Gas Factory Anti-Pattern</span></a>).</span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 240px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
premature decoupling<br />is a common problem</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The Agile approach is to develop the bare minimum that is required to allow the customer to use the software. The very first usable version of a program may be ready in just a few days and have <b>no</b> discernible components. It will later be refactored by decoupling different parts of the design when necessary, and, significantly, <b><span style="color: #990000;">when it is more obvious how to best do so</span></b>. Premature decoupling is a common problem even in Agile development.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">If the team is certain of the best way to decouple (and that decoupling is even necessary) then it can be useful to create a simple component early in the evolution of the software. This simple component will initially be very small (perhaps only a few lines of code) but will be added to and refactored over time, as backlog items dictate.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Over time, components tend to be "owned" by one team (or even one individual). If other teams need changes to the component then they depend on the owner to deliver those changes. The component team then tries to anticipate what dependent teams will require to avoid the dependencies interfering with sprint commitments. As I have mentioned in the past, lots of other unnecessary stuff creeps in when the "owner" is focused on the component and not the backlog - eg: things that are "trivial to add and nice to have", "will definitely be needed eventually", etc. Moreover, these "bonus" features add to the debugging, testing, and planning burden, but most of all they make it harder to refactor the code and make the changes that are actually needed.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
components tend<br />to be owned<br />by one team</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Apart from BDUF, there is the problem that component teams naturally tend to focus just on the component, instead of the backlog items (ie, what the customer actually wants). They will have an idealized picture of what the component should do that is out of tune with what is really needed. They need to focus on customer requirements not component capabilities.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">One consequence is that the dependent team(s) often have to make do with a component that is not really suited for what the customer needs. This results in a misshapen design which inevitably leads to bugs, complexity, and difficult to maintain software. This is a major reason why software degrades over time and has to be written from scratch (see <a href="http://devmethodologies.blogspot.com.au/2012/03/code-degradation.html" target="_blank"><span style="color: blue;">Why Good Programs Go Bad</span></a>).</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="background-color: #f0f0f0; margin: 6px; padding: 6px;">
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">CASE STUDY 1</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">I once worked for a company which had developed a world-leading piece of software that was heavily reliant on the display and manipulation of 2-D graphical objects. The company had developed a remarkably useful library for 2-d computational geometry. They had the good fortune to have a team of mathematicians who were also good C++ programmers who had created this component.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">One of the most powerful features of the software was the display and manipulation of text. Among the text options was the ability to display text on many different base-lines: straight lines, lines at any angle, along a Beziere curve, etc. One of the base-line options was the ability to place the text on the inside or outside of a circle or ellipse. Of course, the geometry library provided an ellipse class which was used for many things and was the obvious thing to use for this type of base-line.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhywnVa6spybvV-4jLs52JwsTodD8go0OSD4ZNQcYVqR5R30dJSHc-q-QWyCChkzMsULzbDI2q2Gq3IsrRr87T8gdV9gW-Fd8oiP5sfxq-qwxfA9pRE21VYtblSD3-jHy73RqM12FjnI2U/s1600/TextAroundEllipse.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhywnVa6spybvV-4jLs52JwsTodD8go0OSD4ZNQcYVqR5R30dJSHc-q-QWyCChkzMsULzbDI2q2Gq3IsrRr87T8gdV9gW-Fd8oiP5sfxq-qwxfA9pRE21VYtblSD3-jHy73RqM12FjnI2U/s1600/TextAroundEllipse.png" height="320" width="108" /></a></div>
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Like all the graphical objects you could apply an affine transformation to the ellipse class - for example, to move, rotate, enlarge, etc. The problem with using an ellipse as the base-line for text was that when it was transformed it was impossible to determine <i>how</i> it had been transformed. Even if you knew the before and after you could not determine what transformation had been applied. For example, an ellipse that was elongated in the X direction could be transformed into an ellipse elongated in the Y direction either by rotating it 90 degrees (or 270 degrees) or by reducing the X scaling and increasing the Y scaling.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
In order to transform the text to match the base-line you had to know where each point on the ellipse had moved to. This was impossible to do if you only had the before and after ellipses to work with.<br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Unfortunately, the "geometry" component team were unwilling to modify their perfect ellipse class to facilitate its use as a base-line. The result was a kludge at a higher level in the code which caused bugs and maintenance problems.</span></div>
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Code Ownership</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Component teams can become very protective of their work. I have seen some go as far as not making the source code available outside the team. Even if they do release the source, it may be strictly forbidden for anyone outside the team to make changes to the component, or even submit code to be included in the component. Change requests often need to be submitted in writing and can take months to be considered, approved and (if you're lucky) implemented.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">As you can imagine, and may have even experienced, this can be very frustrating to a dependent team dealing with a customer who expects responsive changes. The component team may be unavailable, too busy, or simply not interested in making the change. A common problem is that the component team is unwilling to corrupt the purity of their component by acceding to the whims of the customer! Does this sound familiar?</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">One of the principles of XP (the guiding light in these areas of Agile development) is that there should be no code ownership (see <a href="http://www.extremeprogramming.org/rules/collective.html" target="_blank"><span style="color: blue;">Collective Code Ownership</span></a>). Any team should be able to make changes to any of the code that is available to them. Of course, that is not possible with third party components without source code - but that is just another argument for the use of open-source libraries.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The key thing is that, if modifying the component requires specialist knowledge then each team needs at least one developer (even if shared) with that knowledge, or needs to acquire the knowledge. (Of course, the need for lots of specialists is symptomatic of a non-Agile environment as I discuss below.)</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="background-color: #f0f0f0; margin: 6px; padding: 6px;">
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">CASE STUDY 2</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">There was once a company with a software product that dominated it's market throughout the world. It was used by some of the largest companies. Most of these clients required a high degree of customization of the software to suit local markets, regulations, etc.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">This was a large piece of software based around the template design pattern - essentially a "core" system with many extension points. The "core" component was tightly controlled by the main development team at the head office of the company. Several on-site customer teams used the extension points to customise the software to individual customer requirements.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">* This configurability came at a large cost. The main problem was that it added a great deal of complexity making it hard to understand and modify the system. This also had knock-on effects such as poor performance.</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">However, despite it's immense configurability* there were many customer requirements which could not be accommodated, and required (or should have required) core changes. As you can imagine, it was extremely difficult to get timely changes made to the core system, if they were done at all. Scheduling conflicts meant that requests for changes needed to be submitted many months in advance. The teams at client sites found the core team arrogant and uncompromising. The core team were upset at the barrage of stupid and conflicting requests.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
Inevitably the integrity of design became compromised. Many facilities were simply tacked on to client systems rather than being properly implemented in the core. This contorted the design and created maintenance problems. Moreover, the same thing was often implemented by different client teams in different ways - an obvious violation of DRY.</div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;"><br /></span></b></span>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Planning</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Component teams require a lot of coordination and planning to ensure that the components work well together and the development of all components is on schedule. (A great advantage of Scrum is that it requires much less planning work.)</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Integrating components and integration testing is also required, but if coordination (and documentation - see below) between teams is inadequate then integration tasks can blow out enormously.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Using component teams also makes it far more likely that deadlines will be missed. It only takes one team to be late for the whole project to be delayed.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Component teams are also more likely to suffer from uneven workload. Sometimes they have little to do; other times they are overloaded due to different dependent teams waiting for critical functionality. Component teams will invent work if they have none, which can be good if it is refactoring the code to improve its quality (maintainability, efficiency, etc), but it is often unrelated to any current customer requirements.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">A common scenario with highly-specialized component teams is that they are formed near the start of a project then quickly complete most of the required functionality, whence the team needs to be down-sized or even disbanded. This can lead to valued developers leaving the organization because it seems that their work is complete and they have nothing much of interest to hold them. Alternatively, the organization will start inventing work for the component team - but this work tends to become less and less customer-focused.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">A project using component teams often needs to be reorganized which is counter-productive. The truth is, it's hard to build a good team that works well together - at least partly due to personalities (see above). Once you have a well-functioning team you don't want to change personnel too often. Many Agile teams can go unchanged for years, pumping out quality software.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 240px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
Agile teams can<br />go unchanged<br />for years</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">A big problem for a Scrum team working in a large organization is "external dependencies". Scrum teams will strive to finish their sprint backlog by the end of the sprint but are continually frustrated by being dependent on people outside the team. If you have this problem then it indicates that the teams are not really feature teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Documentation</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Component teams tend to produce lots of documentation, since they need to explain the interfaces so that other teams can use their component(s). Of course, as you know, Agile favors "working code over documentation". We all know the problem of documents (time-consuming to create, difficult to understand, incorrect, out of date, etc), so how can we avoid this problem?</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Another Agile principle, <b><i>continuous integration</i></b>, means there is far less need for documentation. If the component and the code that uses it are developed at the same time (by the same team) then this avoids the need for documentation, hand-overs, integration testing, etc. Continuous integration works far better with feature teams than component teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Continuous integration and feature teams work together to reduce the need for large amounts of documentation.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="color: #3d85c6; font-size: large;">Feature Teams</span></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Feature teams are a different way to structure a project. Here we try to avoid having a team that is dependent on any outside person or team in order to complete their backlog items. After all it's only the members of the Scrum team who are completely focused on meeting the sprint objectives.</span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
feature teams<br />can and<br /><i>should</i> specialize</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Note that there is some dispute about what constitutes a feature team. This is caused by some people insisting that feature teams do not specialize. The fact is that feature teams can and often <i>should</i> specialize.</span><br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">For example, a common definition of a feature team (which I believe is inadequate) goes something like this:</span><br />
<br />
<div style="text-align: center;">
<span style="font-family: Georgia, 'Times New Roman', serif;"><span style="font-size: x-large;">“</span></span><span style="font-family: Georgia, 'Times New Roman', serif; font-size: large;">A cross-functional team that has all the skills required to complete items from the product backlog.</span><span style="font-family: Georgia, 'Times New Roman', serif;"><span style="font-size: x-large;">”</span></span></div>
<br />
This definition implies that all feature teams are equivalent since they must be able to complete many or all items from the product backlog. It assumes that the product backlog has, and always will have, items of a similar nature.<br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv9f4tX8B36suuYbBvK7HkDANII2e_HEfJQY9yIljnO79TMJ-kz3ecTsiKLKYb7zgCi2ij63nn4q3LH1LNwmUS8jXFkpTil4Bbg0vC2lhfFpSHfNTVT1Jd6YyUBQ6OYUmjJqjZ4wIv2i4/s1600/FeatureTeams2.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv9f4tX8B36suuYbBvK7HkDANII2e_HEfJQY9yIljnO79TMJ-kz3ecTsiKLKYb7zgCi2ij63nn4q3LH1LNwmUS8jXFkpTil4Bbg0vC2lhfFpSHfNTVT1Jd6YyUBQ6OYUmjJqjZ4wIv2i4/s1600/FeatureTeams2.png" height="189" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Feature Teams</b></td></tr>
</tbody></table>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The problem is that real-world projects have backlog items of amazing variety. Consequently, different feature teams can, and probably should have different capabilities. I discuss this below under <span style="color: #3d85c6;"><b>Specialist Feature Teams</b></span>.</span><br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span>
The diagram at left takes the members of the three component teams (in the component teams diagram above) and creates three feature teams. Note that there is a specialist "Charts" feature team which is the only team that requires developers with knowledge of the geometry library and the charting component.<br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Specialist Feature Teams</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">A feature team can specialize as long as it specializes in things that are important to the customer. As an example you might have a feature team that does not deal with the user interface; instead it handles interfacing with other client systems since it may be critical for the customer to get up-to-date information (eg, inventory levels). A team concentrating on this area of the software would have specialist knowledge very different to that of feature teams dealing with the GUI.</span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 180px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
teams<br />should be<br />long lived</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Of course, even such a specialist feature team should not be so specialized that they <i>can't</i> work on other general backlog items.</span><br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">We also need to keep in mind that feature teams should be long lived. Before creating a specialist team it should be fairly certain that they would have an ongoing supply of high-priority backlog items to suit their speciality.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 320px;">
<div style="text-align: center;">
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Scrum Jargon </b></span></div>
<span style="color: #0b5394;"><span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Product Backlog</b>: prioritized list of tasks for the project</span></span><br />
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Backlog item</b> (PBI): a single task on the product backlog</span><br />
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>General item</b>: a backlog item that can be taken by any feature team</span><br />
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Special item</b>: a backlog item to be taken by a particular feature team</span><br />
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Team Backlog</b>: Subset of product backlog allocated to a specific team</span><br />
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Sprint backlog</b>: the items that a team commits to complete in a sprint</span><br />
<span style="color: #0b5394; font-family: Arial, Helvetica, sans-serif; font-size: xx-small; orphans: 2; text-align: -webkit-auto; widows: 2;"><b>Specialist team</b>: preferred team to deal with special items</span></div>
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Collaboration</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Feature teams are a great example of DIRE. They promote collaboration by getting people who are responsible for a feature to work closely together.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">This collaboration has the advantage that the team members are all focused on a common goal rather than their own small area of interest. Moreover this focus (on high-priority backlog items) is of direct relevance to the customer.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">This sort of collaboration helps avoid the Silo Syndrome (see <b><span style="color: #3d85c6;">Silo Syndrome</span></b> in </span><span style="color: #0000ee;"><u>Production Line Mentality</u></span><span style="color: blue;">)</span> and over-specialization (see below). It also addresses coordination overhead by greatly reducing the need for written documentation, etc.<br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Evolutionary Design</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The basic Agile approach is that changes are made in small increments, so that the software gradually evolves into what the customer wants. By taking "small nibbles", slow but steady progress is made. The overhead of large hand-overs is dramatically reduced and integration problems eliminated. Further, the customer is happier because they can see what is happening. (There may even be a perception that the development took less time than it actually did.)</span><br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 210px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
evolutionary design<br />is easier<br />using feature teams</span></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The only advantage to taking "large bites" instead of "small nibbles" is from economies of scale. However, (as I already discussed in <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank"><span style="color: blue;">Agile Design</span></a>) this is far outweighed by other problems like reduced visibility. To continue the analogy, there is a tendency to bite off more than one can chew.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">However, each small nibble <i>may</i> possibly involve changes in many different areas of the code. Hence a team requires all the skills to make the changes. That is, evolutionary design is easier using feature teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Specialists</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">A big problem with a lot of software, especially much legacy software, is that it can only be modified by a small group of specialists. Whether this happens intentionally or not, it works as a form of job preservation for them. Due to a poor design and a lack of documentation only the "gurus" who understand how it works can modify it; these are usually those who wrote the software in the first place. (Note that by "poor design" I may simply mean that it is unnecessarily complex, though typical legacy applications have many other problems.)</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">These specialists are only required due to the complexity of the design. It's usually not that the component is performing an inherently difficult process; it is simply the way it has been designed and built (and not documented).</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Feature teams are far less likely to create such components since there is no code ownership. An underrated advantage of feature teams is that they reduce dependency on these "specialists".</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Finally, consider the worst case scenario. This is where somebody (usually an existing component team) decides to build an in-house component, rather than use a perfectly adequate off-the-shelf or open-source one. Typically the project must then deal with an expensive-to-implement, poorly-documented, hard-to-use component for little, if any, advantage. A feature team is focused on giving the customer what they want, as simply as possible, so is much more likely to go with the open-source solution.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Feature Team Problems</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Using feature teams does increase the likelihood of conflicting code changes, but this is not a major problem especially if you take my advice and allow some team specialization. Often conflicting changes can be merged with little or no problem. Sometimes it may require a few team members from different teams to get together and work out how to combine the features. Occasionally the teams may need to go back to the PO(s) to point out conflicting requirements.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">One thing that worries many people is that they think chaos will ensue if all developers can modify any of the code - the fear is that the quality of the code will rapidly degrade. This simply does not happen as long if there is someone on the team with the skills needed to do a proper job. (If a team member <i>must</i> make changes outside their area of expertise then it should be carefully reviewed by the relevant expert.)</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">One problem is if there are not enough specialists for all the teams. In this case specialists should be shared between teams, and encouraged to pass on their knowledge. (But remember, as I discussed above, feature teams do not tend to create components that require specialists anyway.)</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><b><span style="color: #3d85c6;">Task Allocation</span></b></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Once you have multiple feature teams the next problem is how to assign tasks to the different teams. This depends on your PO(s) (product owners). If you have a single product owner for all the teams then you need a single product backlog from which all teams derive their own team backlogs.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvyCLIg0Sad9gEdQ6Dw0i1uQXUqNFZhLD6MaRSmdep7ii4czWdGJ_Tb48WEvPjw4U4tZCxJPP8MSrrv_bJU8LEcmNl92ft6dmAlhjzlb4dvmfw7vx4TNEaLxTFsGKFpdjYpcLr_-LA7gU/s1600/Backlog2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvyCLIg0Sad9gEdQ6Dw0i1uQXUqNFZhLD6MaRSmdep7ii4czWdGJ_Tb48WEvPjw4U4tZCxJPP8MSrrv_bJU8LEcmNl92ft6dmAlhjzlb4dvmfw7vx4TNEaLxTFsGKFpdjYpcLr_-LA7gU/s1600/Backlog2.png" height="340" width="400" /></a></div>
<br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Even with multiple PO's it is beneficial to maintain a single product backlog for the project. Of course, this requires the PO's to meet to work out the relative priorities of all items and assign them to different teams. (This can be difficult with vastly different items, like comparing apples and oranges.) As an example, the diagram above shows a product backlog split between three teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">In doing this it is important to carefully consider the task assignments, depending on the work-load and experience of the teams. For example, the same team should probably perform related items from the same Epic. In the diagram you can see that the Charting Team has enough high-priority Charting Tasks, but if they didn't they would need to work on other tasks like the General items. The PO(s) should ensure that each team has enough tasks in their backlog for at least two sprints (based on rough estimates given in grooming).</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">One obvious, but important point, is to ensure two teams do not accidentally end up working on the same task.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<div style="background-color: #f0f0f0; margin: 6px; padding: 6px;">
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">CASE STUDY 3</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">This case study concerns a Scrum team (one of several) in a large company, tasked with supporting and maintaining a legacy application running in thousands of locations. The software was highly configurable (and regularly configured). Apart from the PO and SM the team members were:</span><br />
<ul>
<li><span style="color: #e06666;">5 testers</span></li>
<li><span style="color: #3d85c6;">4 configuration experts</span></li>
<li><span style="color: #bf9000;">3 developers</span> (coding in 3 different languages)</li>
<li><span style="color: #6aa84f;">2 business analysts</span></li>
</ul>
Most of the PBIs (product backlog items) were <span style="color: #3d85c6;">configuration changes</span> - requiring configuration experts, testers and often a business analyst, but no developers. Apart from config. PBIs there were also PBIs for small <span style="color: #bf9000;">software changes</span> and occasionally large developments - mainly requiring coding but with possible involvement from anyone in the team. Even if there were no software enhancements in the product backlog there were always low-priority (usually historical) bugs to fix.<br />
<div>
<br /></div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The product backlog typically contained mostly configuration and general tasks with a few low-priority bug fixes (see <i>Typical Product Backlog</i> in the diagram). For a fortnightly sprint the sprint backlog would be composed of the highest priority tasks (mainly config) plus a few development tasks to give the coders something to do.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdDW9w64j2h9nSoo8Gxa29bKq7XtvyB5G2Rwzrn5w419fXsPJXbJnT6K6EbBoXs5jB68TZkX3S7O6zdroHiFbDe2GxCu8mF4GZEbj_-M95bjVBWGQtSUyt8fbR62RhdNfzAEEBWzxLuZM/s1600/TeamBacklog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdDW9w64j2h9nSoo8Gxa29bKq7XtvyB5G2Rwzrn5w419fXsPJXbJnT6K6EbBoXs5jB68TZkX3S7O6zdroHiFbDe2GxCu8mF4GZEbj_-M95bjVBWGQtSUyt8fbR62RhdNfzAEEBWzxLuZM/s1600/TeamBacklog.png" height="355" width="400" /></a></div>
<br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">However, there were sometimes high-priority developments, in which case the product backlog would look very different (see "<i>Development</i></span>"<i> Backlog</i> in the diagram).<br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">The major problem that the team experienced was due to the mix of tasks. Most of the time the high priority tasks were configuration and of little or no consequence to developers. Sometimes there was a major development that was of no interest to most of the configuration experts. In most meetings (planning, standup, grooming) there was a lot of discussion that was only understood by a subset of the team, which meant there was a huge amount of time being wasted by people in meetings that were not important to what they were focused on.</span><br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimwQdevH-b2Z9u2htdUutY31em8TZvtnCqqWG99m8VTddi4TUlXrokYbT3O0gsLtX5oWg9y1LO-LrktOro6qNR5KD9SRedb-85FNpBWS22hxQ7e7t2Qx9268caB_v4r6yMslqr6Qcawws/s1600/CSComponent.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimwQdevH-b2Z9u2htdUutY31em8TZvtnCqqWG99m8VTddi4TUlXrokYbT3O0gsLtX5oWg9y1LO-LrktOro6qNR5KD9SRedb-85FNpBWS22hxQ7e7t2Qx9268caB_v4r6yMslqr6Qcawws/s1600/CSComponent.png" height="165" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Component Teams</b></td></tr>
</tbody></table>
There were other problems such as many tasks being highly dependent on external people - indicating that this was not really a feature team. Another thing was that the configuration guys preferred to have a standup at 8:30am, while the developers preferred 10:00am. It was also demoralizing for the developers to be continually handed low-priority "scraps".<br />
<br />
It was obvious (not just because the team was too big) that the team should be split into multiple teams. So how would you split up the team?<br />
<br />
It was suggested to use a team structure of Testing, Configuration and Development teams. This was similar to the teams that existed before we adopted Scrum. See the Component Teams diagram above.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiNc0JO9izSTtzls8pAB8sAAsoWpUXnuyxaA3OJyUpQg9Dy5JbPnt37ppSKsnxWZAl8mCzwlX6i3olEypfqPZV7Pmm45R_w70kbi3s4W45PccH7f0wVo-jPW6U4vGVzoU2AR2xd51Ck1w/s1600/CSFeature.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiNc0JO9izSTtzls8pAB8sAAsoWpUXnuyxaA3OJyUpQg9Dy5JbPnt37ppSKsnxWZAl8mCzwlX6i3olEypfqPZV7Pmm45R_w70kbi3s4W45PccH7f0wVo-jPW6U4vGVzoU2AR2xd51Ck1w/s1600/CSFeature.png" height="161" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Feature Teams</b></td></tr>
</tbody></table>
A better approach would be to create two (or even three) feature teams to deal with the types of backlog items that were commonly encountered. The approach I recommended was to have a Configuration Team that dealt with configuration backlog items and a Development team that would deal with programming tasks (and other tasks if there was not enough development). See the Feature Teams diagram at right.<br />
<br />
Each team would have their own backlog derived from the product backlog (see diagram below) and would not have to deal with meetings and discussions about tasks that they did not need to focus on. (Of course, that did not mean whatsoever that communication between the teams was discouraged, when necessary.)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0T-uIEUWO_8-JOE3CvSyGvPAS1UWNIoq85yvbcd1Ftm1ayGneSqirXkrrJjz8MH4mm6xbtDciARLauaIMti39AZEM3A4U0xOgCPPGY1_6v5Mk3dHHrIZzPzIjRqgOetdOXhyiKdD8WhE/s1600/TwoTeamBacklog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0T-uIEUWO_8-JOE3CvSyGvPAS1UWNIoq85yvbcd1Ftm1ayGneSqirXkrrJjz8MH4mm6xbtDciARLauaIMti39AZEM3A4U0xOgCPPGY1_6v5Mk3dHHrIZzPzIjRqgOetdOXhyiKdD8WhE/s1600/TwoTeamBacklog.png" height="356" width="400" /></a></div>
<br /></div>
<br />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><span style="color: #3d85c6; font-size: large;">Conclusion</span></span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">An important part of implementing Scrum is to carefully choose the composition of teams.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">First, it is important to consider personalities when building teams. This requires good judgement and a measure of luck to get right. Don't be afraid to experiment and change teams around if things are not working.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">From an Agile standpoint it is also important to get the skill mix right. Scrum teams should be formed around customer needs <b>not</b> around the software architecture -ie, use <i>feature teams</i> <b>not</b> <i>component teams</i>. One of the most frustrating things for a Scrum team is repeatedly failing to complete sprints due to external dependencies.</span><br />
<br style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;" />
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">As well as creating external dependencies, component teams also:</span><br />
<ul>
<li>need more planning and coordination effort</li>
<li>tend to produce overly complex designs</li>
<li>create and depend too much on specialists</li>
<li>focus on their own small world instead of the big picture</li>
</ul>
In contrast, feature teams encourage collaboration and avoid the problems of component teams. Amongst their advantages are such diverse elements as:<br />
<ul>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">keeping all team members focused on the customer</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">making specialization less likely (see <a href="http://devmethodologies.blogspot.com.au/2014/12/production-line-mentality-and-silo.html" target="_blank"><span style="color: blue;">Production Line Mentality</span></a>)</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">putting together team members that need to work together (see <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a>)</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">allowing teams to work without being frustrated by external dependencies</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">focusing on only delivering what is required now (see <a href="http://devmethodologies.blogspot.com.au/2014/09/agiles-fifth-element.html" target="_blank"><span style="color: blue;">Fifth Element</span></a>)</span></li>
</ul>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">In brief the rules/attributes for feature teams are:</span><br />
<ul>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">the team has all the skills to tackle tasks on <i>their</i> backlog</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">every team member <i>could </i>make a contribution to each backlog task</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">specialist teams are useful if the backlog has different classes of PBIs</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">you anticipate enough special items to justify creation of a specialist team</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">feature teams are stable and long-lived</span></li>
<li><span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">feature teams are highly collaborative and focused on the customer</span></li>
</ul>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Next week I will look at personalities and why teams do not collaborate.</span></div>
<div>
<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;"><br /></span></div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com6tag:blogger.com,1999:blog-7237530825191390698.post-47492749292508030362015-03-30T08:40:00.000+11:002015-04-10T13:05:30.711+10:00Scrum Team SizeOne of the most important aspects of a Scrum team performing at their best is to get the size and composition of the team right. Size is simple, but it's importance is not generally recognized or explained. So I have taken it on myself to explain it here.<br />
<br />
Composition is a bit trickier. Its not just about skill sets (which I already covered last year - see <a href="http://devmethodologies.blogspot.com.au/2014/12/agile-roles.html" target="_blank"><span style="color: blue;">Agile Roles</span></a>) but also about personalities and how members get along. Another consideration is how and how often teams should be reorganized. Due to lack of space and time I will leave the discussion of team composition until next week.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Scrum Team Size</span><br />
<br />
I have worked in teams from a size of 3-4 to a team in the range of 14-18. In my experience a good Scrum team size is about five with a maximum of about seven. Depending on the people and the type of project you might be able to get away with a team size of nine.<br />
<br />
I have read many books and articles on Scrum and the absolute maximum team size is always specified as either seven or nine. For example, I am currently reading an excellent book called <b>Succeeding with Agile</b> by Mike Cohn who says that the accepted rule is a team size of five to nine, but recommends (page 178) the less regimented rule of <i>a team that you can feed with two pizzas</i>. Mike mentions that this is a convention used at Amazon. (I'm not sure if this means that you can have a team larger than nine if you get larger pizzas or smaller developers:) Later on I will tell you how to split a team that is too big.<br />
<br />
Scrum rules also give a minimum size of five, though I have also seen three mentioned. In an extreme case a small software company may have to make do with a team of three - two developers (one of whom acts as a part time Scrum Master) and a Product Owner (hopefully provided by the client).<br />
<br />
Every Scrum article, book, expert and consultant emphasizes the importance of the team size, so don't question it! If you <i>insist</i> on questioning it, despite my advice, then I can give you several arguments which I explain in the next sections.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Social Loafing</span><br />
<br />
Social loafing has been extensively studied starting with RingelMann about a century ago - see <a href="http://en.wikipedia.org/wiki/Ringelmann_effect" target="_blank"><span style="color: blue;"><i>Ringelmann Effect</i></span></a>.<br />
<br />
I talked about this at length in <a href="http://devmethodologies.blogspot.com.au/2015/02/scrum-communism.html" target="_blank"><span style="color: blue;">my previous post</span></a>. In summary, social loafing is the effect that as more people work together to perform a task then the less effort each individual contributes to the task. The effect increases as the number of people increases but is measurable even with two people. Most studies show a pronounced drop when the group size reaches around seven to twelve people depending on the type of task.<br />
<br />
Try to limit the size of Scrum teams if for no other reason than this.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Visibility</span><br />
<br />
An important feature of Agile that counteracts social loafing is visibility.<br />
<br />
Visibility was originally designed to assuage the fears of the customer. The PO (and other stakeholders) can, at a minimum, see that progress has been made at the end of each sprint. If they want even greater assuagement (is that a word :), they can examine the sprint board on a daily basis. Of course, the PO does not, and need not, know what each team member is doing but they can easily see progress as tasks move to "done" status.<br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 180px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
peer pressure<br />counteracts<br />social loafing</span></div>
However, visibility is also important within the team. In Scrum everyone in the team should know what everyone else is doing. This is essential if the team is to self-manage and self-organize effectively. It becomes very obvious when someone is not pulling their weight. The resulting peer pressure counteracts social loafing.<br />
<br />
Obviously, as the team size gets bigger it becomes harder for team members to understand what everyone else in the team is doing. Studies have shown that even the most skilled multi-taskers can at most keep track of nine separate activities. My experience, and that of many others, is that a team of nine is the absolute maximum, while even seven is getting too big.<br />
<br />
I have heard the argument that a Scrum team is like a sports team (such as a rugby team), and since a rugby team has 15 players you should be able to have a Scrum team of that size. (First, I would say that a rugby team is composed of two cooperating teams - the forwards and the backs - but I don't know enough about the sport to argue that further.) It's true that a Scrum team is a bit like a rugby team but the main difference is that individuals in sports team have much greater visibility - it is much more obvious what each player is doing. Another difference with sports, is that typically only a one or a few players are actively involved in the game at any time, whereas in a Scrum team everyone is working diligently all the time.<br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 210px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
the major benefit<br />of the daily standup<br />is visibility</span></div>
Scrum practices are important. In particular, the major benefit of the daily standup is visibility. This is why it is very important to make sure the standup is working properly as I discussed here a few years ago (see <a href="http://devmethodologies.blogspot.com.au/2012/10/scrum-standup.html" target="_blank"><span style="color: blue;">October 2012</span></a>).<br />
<br />
Remember, visibility is essential for counteracting social loafing. The team size should be small to facilitate this visibility otherwise team members can easily fade into the background.<br />
<br />
<div style="background-color: #f0f0f0; margin: 6px; padding: 6px;">
<span style="-webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px; border-collapse: separate; border-spacing: 0px; font-family: Tahoma; font-size: xx-small; font-style: normal; font-variant: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"><span style="color: #6fa8dc; font-family: Arial, Helvetica, sans-serif; font-size: large;">CASE STUDY :)</span></span><br />
<br />
A colleague once worked in a Scrum team that was far too big at a size of more than 20. As an "experiment" he tried several different strategies to avoid talking or saying anything useful at the daily standup. Due to the size of the team he found it very easy. Sometimes nobody would notice if he did not even attend! <b>This demonstrates how important a small team is for visibility.</b></div>
<br />
<span style="color: #3d85c6; font-size: large;">Team Spirit</span><br />
<br />
Having a good team spirit is another way to counter social loafing. Many of the principles and practices of Agile encourage the team to work closely together which fosters team spirit.<br />
<br />
To invoke another sporting analogy consider times in relay events such as swimming, running, etc. According to the <i>Ringelmann Effect</i>, times of athletes in relay events should be slower than their times in individual events. However, it is not unusual for athletes to perform as well or even better in a relay. This is entirely due to team spirit.<br />
<br />
There are many aspects of Agile that promote team spirit.<br />
<ul>
<li>focus on customer requirements</li>
<li>having a clear and common understanding of team goals</li>
<li>encouraging collaboration and having the team self-organize</li>
<li>rewarding the team, rather than the individual team members</li>
<li>encouraging open, honest communication</li>
<li>empowerment and self-management</li>
<li>motivation of team members to do their part</li>
<li>team members feel that they are making a valuable contribution</li>
</ul>
Notwithstanding Agile practices, team spirit may be affected by other factors, such as the personalities of the team members (something I talk about next week), competition with other teams, etc.<br />
<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 190px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
team spirit decreases<br />the larger<br />the team becomes</span></div>
My point here is that team spirit diminishes the larger the team becomes which is another reason not to have a large team.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Competitive Spirit</span><br />
<br />
Talking about team spirit I recalled that another way to get teams motivated is to encourage a bit of inter-team rivalry. I have actually only seen this work well once, where I was working with 12 to 16 recent university graduates. There was an interesting coincidence in that the group was almost exactly split between electrical/electronic engineering and software engineering graduates. I split the group into two teams based on their degree and tried to objectively compare the performance of each team, even displaying graphs of work completed. This worked well to motivate the teams, at least for a while.<br />
<br />
However, I recommend caution in using this approach. First, you probably shouldn't do this if the teams need to work together in any significant manner - it does not encourage collaboration. Also you must keep it friendly and be entirely honest and open about it, otherwise it will be seen as manipulative.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Over-Specialization</span><br />
<br />
Another problem with a large team is that team members become prone to <a href="http://devmethodologies.blogspot.com.au/2014/12/production-line-mentality-and-silo.html" target="_blank"><span style="color: blue;">Production Line Mentality</span></a>. With many developers there is too much opportunity to specialize in one particular aspect of the team's responsibilities. (The same can happen with entire teams as I discuss next week.) This leads to developers who are unwilling, even unable, to perform any tasks outside their area of expertise.<br />
<br />
This has many undesirable consequences. First, there may be times when the specialization is not required and the specialist has nothing to do. Conversely, if the specialist leaves or has <i>too much</i> to do then there is often nobody with the experience in the area who can take over or help.<br />
<br />
But the worst problem, in my opinion, is that specialists tend to concentrate on the their own narrow area of focus, rather than being aware of, and striving to achieve, the goals of the team.<br />
<br />
Don't get me wrong. It is often very useful to have developers with specialist knowledge. However, they should be willing and able to work in other areas as required (On the other hand you should not waste their talents unless there is a very good reason.)<br />
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br /></div>
<span style="color: #3d85c6; font-size: large;">Coordination</span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
So Scrum helps to counter <i>social loafing</i>, but there is another reason for the <i>Ringelmann Effect</i> besides social loafing. For complex tasks, such as software development, coordination overhead becomes an even more significant problem.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0BMcH0ZUiDRAcFD4Aq43HNmHCyQ5rmCiUVHyhRwz4TqxJRhRfuI74AEcaxqm7EEtb-CzjKxCO7TLROl_71CZffv6zlETnyJfyQS-mqwH1BlNfc_dlUs4wD-MZi9nNg2Oj0CHUbk2KxPQ/s1600/TenCircle.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0BMcH0ZUiDRAcFD4Aq43HNmHCyQ5rmCiUVHyhRwz4TqxJRhRfuI74AEcaxqm7EEtb-CzjKxCO7TLROl_71CZffv6zlETnyJfyQS-mqwH1BlNfc_dlUs4wD-MZi9nNg2Oj0CHUbk2KxPQ/s1600/TenCircle.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Complexity Grows Exponentially<br />
as Team Size Increases</td></tr>
</tbody></table>
<br />
There are two aspects to coordination. First, there are technical issues to do with building the software - these are not addressed by splitting into smaller teams because there will still be a need for inter-team communication. It might be useful if there is a logical separation of tasks based on feature areas of the software so that the new teams can concentrate on different areas, but this does not reduce the need for coordination, just contains it within the separate teams.<br />
<br />
The other issue of coordination is getting everyone on the team to work together to knock off the sprint tasks. This is where having two small teams instead of one large one can reduce coordination effort.<br />
<br />
Some developers try to take this argument to the extreme, arguing for a "team" size of one. It's true that the most efficient way to produce software may be just to have one good developer go at it full-time, without interruptions. However, there are disadvantages to having too small a team as I will discuss next.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Minimum Size</span><br />
<br />
So much for the maximum size - what about the minimum?<br />
<br />
By extrapolation of the arguments above you might conclude that a team size of one or two is best. It's true that a lot of problems, especially of coordination, disappear when a single developer (or even two) works on a project. There is actually some validity in this argument - for example, there are many great pieces of software that have been created by one or two people.<br />
<br />
But I think the main motivation for this argument is that most developers have the personality type that prefers to work alone. Moreover, industry training and years of behavioral conditioning have reinforced this preference. I don't have enough space to elaborate here but this is important enough to warrant a future post.<br />
<br />
You probably already concede that for large projects using one very small team is silly. It might be most efficient to have one developer take five years on a project but in that time priorities may have changed. Even if inefficient, it is likely preferable, for example, to assemble a team of eight and complete it in one year. There is also increased risk due to the single point of failure.<br />
<br />
On the other hand, if a large project is tackled by many small teams, then this is effectively the same as having one large non-communicative team. Unless you are able to split the work into many independent parts then you must encourage communication and collaboration by building teams of at least four.<br />
<br />
So I recommend not having a team size smaller than four or five. If absolutely necessary you could have a team of two developers (one of which is a part-time Scrum Master) plus a Product Owner (possibly part-time and possibly supplied by the client).<br />
<div>
<br /></div>
<span style="color: #3d85c6; font-size: large;">Splitting Teams</span><br />
<br />
The obvious question now is if you have a large or growing team, how do you split it?<br />
<br />
Once a team gets to a size of 8 then you should look at splitting the team into two. One way to do this with a team composed of one PO, one SM and 6 developers is to create two teams of 5 which share their PO and SM and have three developers each. If you already have teams with shared members (for example two teams of 7) then you can look at splitting into three teams of 5.<br />
<br />
I have heard the argument that sharing a PO or SM between teams means more work for them. But working with two small teams should not really create much more work for the PO/SM than one large team. But it *will* save a great deal of time for the other team members if they do not have to attend long standups, planning meetings, etc (as well as having all the other advantages of small teams that I mentioned above).<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<div style="text-align: center;">
<b><span style="color: #3d85c6;">Shared PO </span></b></div>
<br />
Having a shared PO between two teams should not result in more work than a PO with one big team.<br />
<br />
However, I do not recommend having a PO shared by more than two or three teams. This would just be too confusing.</div>
Another argument I have sometimes heard, for not splitting a team, is that there is no natural way to separate a large team as they are all doing similar work. It doesn't matter, split it anyway. Two teams can even work from the same product backlog, as long as they have a shared PO. Of course, it is probably best to have an equal mix of experience, familiarity with Scrum, etc on both new teams.<br />
<br />
A crucial point when splitting is to resist creating "component" teams (teams that create components for other teams to use). Each new team should have<b><span style="color: #990000;"> all the skills to create new features</span></b>. In other words each team should be capable of completing any (or a large proportion) of tasks from the product backlog. This is another good example of <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a> since it gets people on the same team to work together towards the same goal. Not only does it promote customer focus, but avoids problems like external dependencies, over-specialization (as above), etc as I will explain next week when we look at team composition.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Conclusion</span><br />
<br />
There are several effects detrimental to large teams. Generally these effects are seen in teams of any size but start to really kick-in once a team reaches about seven or eight people. These include:<br />
<ul>
<li>increase in social loafing</li>
<li>reduction in team spirit</li>
<li>coordination overhead</li>
<li>inefficiencies due to over-specialization</li>
</ul>
At the other extreme, having very small "teams" of one or two people may address these problems, but to do this the work must be divided into many different tasks for each of the "teams". This introduces other problems:<br />
<ul>
<li>some tasks are not easily divided</li>
<li>some tasks may take longer than others</li>
<li>increased coordination <i>between</i> teams</li>
<li>single points of failure</li>
</ul>
Moreover, when you have many small teams working together on a large project you effectively have one large loosely-coupled team, whence the large team problems start to rear their ugly heads again.<br />
<br />
It seems that, even with their drawbacks, teams of size five to eight are the best size. The good news is that team spirit and many Agile practices will minimize these drawbacks. In particular, the visibility provided by Scrum's daily standup greatly reduces social loafing.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com3tag:blogger.com,1999:blog-7237530825191390698.post-71445686893232934482015-02-09T02:08:00.001+11:002015-09-01T01:03:47.112+10:00Scrum == Communism ?I have heard it said, and have had the feeling myself, that Agile (Scrum in particular) is a bit like <b><i>Communism</i></b>. The follow-on from this is that Scrum is doomed to failure and/or that people won't accept it (presumably on ideological grounds). Let's explore the validity of this argument.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitZj6-56x9nyi4Ds-tc7vMosl2gvTtCmyW9Nqm28RUKILFIrYSFw-3BlBSDtYgw5FGDWQD-zSy3sJJy-GaFfsLvMxp2fEz8OmL8vTXLQ7mvYALdDSI7uNqknlfQs2-A70ZTsuxAuOYcms/s1600/ScrumStar.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitZj6-56x9nyi4Ds-tc7vMosl2gvTtCmyW9Nqm28RUKILFIrYSFw-3BlBSDtYgw5FGDWQD-zSy3sJJy-GaFfsLvMxp2fEz8OmL8vTXLQ7mvYALdDSI7uNqknlfQs2-A70ZTsuxAuOYcms/s1600/ScrumStar.png" width="153" /></a></div>
<span style="color: #3d85c6; font-size: large;">What is Communism?</span><br />
<br />
First we need to decide what <i>Communism </i>is. I have always been a little vague on this but here are two simple definitions.<br />
<ol>
<li>The workers control the means of production.</li>
<li>Classless society where you give what you can and you get what you need.</li>
</ol>
I will only discuss the first definition to say that it is not particularly relevant. First, the means of production in software development is the computer hardware and the brains of the developers. I don't think it's a big deal who owns the computers, and I don't think anyone would argue that the company you work for owns your brain. Of course, owning some of the company you work for (eg, stock options) may be a motivator but probably does not make much difference to the use of Scrum.<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 220px;">
<span style="font-size: x-small;">Please note that this article is in no way politically motivated or an attempt to promote <i>Communism </i>or any other political system.
</span></div>
<br />
I think the 2nd definition is more useful to our discussion. So the question is: Is there any similarity between a Scrum team and <i>Communism </i>as in the 2nd definition? Let's look at the definition in detail by splitting it into three parts...<br />
<br />
<b style="color: #3d85c6;">Classless society</b><br />
<br />
<div style="float: right; line-height: 24px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
"all team members <br />are equal"</span></div>
A scrum team is self-organizing. There are no bosses (within the team) to tell team members what to do. Of course, the PO determines the product backlog which gives direction to the team, but how the team accomplishes their goals is completely up to them.<br />
<br />
Note that you shouldn't make the mistake of thinking that "self-organizing" means the team can do what they want - that would instead be <b><i>anarchism</i></b>. The team must work within the bounds set for them by senior management, the product backlog and the rules of Scrum. It is an advantage of Scrum that self-organizing teams usually organize themselves more efficiently and flexibly than an individual manager can.<br />
<br />
<span style="color: #3d85c6;"><b>Contribution (give what you can)</b></span><br />
<br />
Just because all team members have equal rights does not imply whatsoever that they have equal abilities. Obviously team members will vary in what they can contribute depending on experience, knowledge and aptitude.<br />
<br />
<div style="float: right; line-height: 24px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
"everyone contributes according to their ability"</span></div>
An advantage of Scrum is that team members, after time working together, grow to know of their colleagues' abilities and weaknesses far better than any outsider. This is one of the reasons that self-organization works so well. This, plus being empowered, means that the abilities of individuals are made far better use of. Further, the sense of camaraderie encourages the team to work towards the same end.<br />
<br />
This is how <i>Communism </i>is intended to work but in practice "Communist" states fail because there is no incentive to work to your best ability. Scrum only works because in a small team everyone knows who is not pulling their weight and there is a team spirit and "peer pressure" to do your best.<br />
<br />
<span style="color: #3d85c6;"><b>Rewards (get what you need)</b></span><br />
<br />
In <i>Communism </i>(in theory) there are no privileged individuals. Nobody has special benefits. Everybody is treated the same. Similarly, in Scrum the whole team is rewarded, regardless of the contribution of different individuals.<br />
<br />
<div style="float: right; line-height: 24px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
"everyone is rewarded equally"</span></div>
This is another important advantage of Scrum. While rewarding on an individual basis encourages competition and hard work, it also promotes rivalry and virtually destroys collaboration.<br />
<br />
A common argument against Scrum is that those in the team who make a greater contribution will be aggrieved because they get no better treatment than the worst performers. In my experience this rarely happens unless there are one or two team members not pulling their weight (in which case the team has the right to vote them out of the team). Generally, team members are committed to the team and not aggrieved when they know that everybody is doing their best.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Ringelmann Effect</span><br />
<br />
So if Scrum is like <i>Communism</i>, the next logical conclusion is that it is doomed to failure like numerous Communist states. Wrong! There is a fundamental difference - a Scrum team is much smaller. In my opinion <i>Communism </i>(and Scrum) <i>can</i> work well for a small number of people. The ideal size is probably around five. Ten is stretching it. It can't work at all with a team size of 20 and there is no hope at all with a population of millions.<br />
<br />
This is all due to the <a href="http://en.wikipedia.org/wiki/Ringelmann_effect" target="_blank"><span style="color: blue;"><i>Ringelmann Effect</i></span></a>, which has been known, and extensively studied for more than a century. The <i>Ringelmann Effect</i> essentially says that the larger the group performing a task the less productive each group member becomes.<br />
<br />
The interesting thing is that when the size of the group exceeds about eight the
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
* The actual "plummet level" varies depending on the type of project. For a complex project it may be just 6 people. For a well-understood project it may be 10 or even 12.<br />
<br />
My rule of thumb is to follow the Scrum guideline of a maximum team size of 9, but preferably around 5.</div>
productivity, per person, plummets*. Studies have shown that a team of 14 people will produce less than a team of seven - that is total output <i><b>not</b></i> per capita output. Many would expect that by doubling the number of people in the team, the output, if not doubled, would at least increase, but it actually falls!<br />
<br />
What is the cause of the Ringelmann Effect?<br />
<br />
After much study it is generally recognized that there are two principal causes: social loafing and coordination overhead.<br />
<br />
<span style="color: #3d85c6;"><b>Social Loafing</b></span><br />
<br />
Social loafing is the name for the phenomenon where people exert less effort to achieve a goal when working in a group than when working alone. Further, as the group size increases the average (per capita) effort decreases. The interesting thing is that this is often unconscious - the individuals may not even be aware that they are not trying as hard!<br />
<br />
Social loafing is the main effect that Ringelmann discovered in his original experiments early last century. He found that, given the task of pulling a rope, the more people that are pulling the less was the average force generated. Importantly, when the size of the group reaches 7-8 then the average effort falls quickly.<br />
<br />
What is the relevance of social loafing to this discussion?<br />
<br />
First, I believe that social loafing is the principle reason for the failure of (large scale) <i>Communism</i>. However, social loafing in a Scrum team is reduced since team size is restricted to 9, and is typically 5 or 6. Moreover, social loafing is well managed by other Scrum practices such as the daily standup and is often counteracted by such things as team spirit.<br />
<br />
One aspect of Ringelmann's experiments that we should consider is that the experiments placed people in groups at random. I believe that if the groups had been given an incentive and were allowed to generate any sort of team spirit then the results may have been significantly different. For example, instead of simply pulling a rope with a group of strangers perhaps the groups could have been organized into "tug of war" teams that pulled against each other.<br />
<br />
The benefit of "team spirit" is born out by the fact that in sporting events (swimming, running, etc) an individual will often perform at a higher level in a relay event than in an individual event (see <a href="http://onlinelibrary.wiley.com/doi/10.1002/ejsp.1875/abstract" target="_blank"><span style="color: blue;">Hüffmeier et al</span></a>), though I suspect this depends on the specific individual and team involved.<br />
<br />
Another important effect, which counteracts social loafing, is peer pressure. Peer pressure is often portrayed negatively but can have beneficial effects. The visibility of the daily standup (see <span style="color: #3d85c6;"><b>Why It's Good</b></span> in <a href="http://devmethodologies.blogspot.com.au/2012/10/scrum-standup.html" target="_blank"><span style="color: blue;">Scrum Standup</span></a>) means that the team quickly becomes aware of any members who are not pulling their weight. I will mention (again) that for this to be effective the team must be of a small size (9 or less) otherwise the team will not be aware of what everyone is doing and individuals can fade into the background.<br />
<br />
<b><span style="color: #3d85c6;">Coordination</span></b><br />
<br />
Coordination refers to getting everyone working towards the same goal and simply communicating effectively with other team members when necessary. As the goals of the team, and the means to achieve them, become more complex, coordination rapidly becomes important. Once social loafing is under control (as discussed above) coordination become the more significant effect affecting the team's performance.<br />
<br />
The problem of coordination affects any group endeavor so it should affect a Scrum team just as it would affect a Communist state. Again there is the obvious difference that a Scrum team has no more than nine team members so -- coordination is easier the smaller the team.<br />
<br />
I will also mention in passing that some of the techniques of Scrum such as dividing a project into many small iterations avoid many of the problems of coordination. A proper discussion of this will have to wait for a later time.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Summary</span><br />
<br />
In Scrum, all team members are equal, at least within the team. Team members contribute according to their abilities. The whole team is rewarded according to their achievements. Scrum and Communism <i>do</i> look to be similar.<br />
<br />
So is Scrum doomed to the same fate as <i>Communism</i>? Not at all!<br />
<br />
As was discovered by Ringelmann, social loafing can greatly affect performance of a team. This is a major problem for <i>Communism </i>and for Scrum. However, social loafing does not really kick in until the team size reaches eight or more, which is why Scrum teams should not be larger than 8 or 9.<br />
<br />
Scrum practices also help. The visibility in the daily standup provides peer pressure which counteracts social loafing. Further, team spirit is enhanced by having the team work towards a common goal (ie, finishing the sprint backlog) which also overcomes loafing.<br />
<br />
It is generally agreed that <i>Communism </i>failed due to a lack of incentives -- people don't excel when they are given no reason to. This is often taken to mean that people are inherently greedy. But not all (or even most?) people are motivated by money/material possessions. A great motivator in a small team can be helping your colleagues and doing your part for the success of the team.<br />
<br />
My conclusion is that Scrum <i><b>is</b></i> like <i>Communism </i>but on a small scale. <i>Communism </i>(and Scrum) can work well for a small group of people. It's just that <span style="color: #660000;"><b>it does not scale well</b></span>.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-59740511882314042272015-01-31T23:34:00.000+11:002015-02-03T18:41:19.103+11:00Lean Is Not Agile<i>Lean Software Development</i> ostensibly tries to apply many of the principles of <a href="http://en.wikipedia.org/wiki/Lean_manufacturing" target="_blank"><span style="color: blue;"><i>Lean Manufacturing</i></span></a> to software development. I first remember reading about <i>Lean Manufacturing</i>, and the Japanese Quality Assurance movement, more than 20 years ago - before I had even heard of Scrum and well before the Agile Manifesto. In fact when I first read about XP (in '98 or '99) I remember thinking that a lot of ideas came from the quality assurance movement and even Lean.<br />
<br />
However, in the last few years I have seen a lot of people saying or assuming that <i>Lean Software Development</i> is a "variety of Agile", like XP, Scrum, etc are. For example, I recently saw an advertisement for a course at a reasonably well respected university on <i><b>SCRUM vs LEAN: Agile Methodologies Analysed and Compared</b></i>.<br />
<br />
Let's be clear on this, Lean is <i><b>not</b></i> a variety of Agile.<br />
<div style="float: right; line-height: 32px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
“ Lean is not<br />
a variety<br />
of Agile ”</span></div>
<br />
<span style="color: #3d85c6; font-size: large;">Brief History</span><br />
<br />
<i>Lean manufacturing</i> grew up as part of the Japanese Quality Assurance Movement around the middle of the last century. This movement was a major contributing factor in Japan's rise in a few decades to be the world's manufacturing powerhouse. The main focus of <i>Lean Manufacturing</i> is eliminating waste in its many forms.<br />
<br />
The success of Japan's QA movement meant the ideas spread to other countries and many different industries. The ideas of QA and <i>Lean Manufacturing</i> found their way into SQA (software quality assurance) around the early 1990's. A great deal of them also found their way into Agile (perhaps via XP) in the late 1990's, but Agile is more than just a rehashing of the ideas of SQA and Lean.<br />
<br />
A fundamental principle of QA/Lean is the concept of "<b>Right First Time</b>", which is trying to do things properly by <b>eliminating mistakes</b>. Agile outright rejected this idea, not in all things, but in the most crucial aspect of the software development process - how the software is specified and designed.<br />
<br />
Agile is based on evolving the design based on responsive feedback. The assumption is that waste is unavoidable and that an emphasis on eliminating waste is counter-productive.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Lean Software Development</span><br />
<br />
About 10 years ago Mary and Tom Poppendieck wrote a book called <b><i>Lean Software Development: An Agile Toolkit</i></b>, which apparently started a Lean movement "within Agile". I think I first heard of this book a few years ago but I have only just started reading it. I haven't had time to read all of it yet, but what I have read I agree with absolutely. It explains many of the principles and practices of Agile really well.<br />
<br />
The only problem I have with the book is that it tries to apply "<i>Lean Manufacturing</i>" to justify Agile practices. The implication is that the core idea behind Agile is the lean philosophy of eliminating waste. This I find entirely fallacious.<br />
<br />
The critical flaw in the premise of the book is demonstrated by this direct quote:<br />
<br />
<div style="background-color: #f0f0f0; margin: 12px; padding: 6px;">
<div style="text-align: center;">
<span style="line-height: 115%;"><span style="font-family: Times, Times New Roman, serif; font-size: large;">“</span></span>Just as manufacturing processes are continuously improved by production workers, so must a software system be continuously improved by developers.<span style="font-family: Times, Times New Roman, serif; font-size: large;">”</span></div>
</div>
<div style="text-align: right;">
- see <b>Tool 19: Refactoring</b> on page 137</div>
<br />
The problem here is that it is confusing two different things: the manufacturing process and the product being manufactured.<br />
<br />
A core principle of <i>Lean Manufacturing</i> and QA in general is to attempt to continually improve the process by which a product is created. But the actual <b>product</b> is not normally modified only the way in which it is made. For example, a watch manufacturer does not sell a watch (version 1.0) with only an hour hand, with the promise that later upgrades would add features such as a minute hand, increased accuracy, etc.<br />
<br />
Applying this principle from <i>Lean Manufacturing</i> to software development means continually improving the way the software is developed. That is, Lean does not say to continuously refine the software (the product), only the <b>process</b>.<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="font-size: x-small;"><b><i>Rework</i></b> is a QA term meaning work that has to be fixed or repeated because it was not done correctly the first time.</span></div>
Hence the primary application of Lean ideas to software would be to improve that part of the process which far and away causes the most mistakes and <b><i>rework</i></b> - poorly understood, poorly communicated and continually changing requirements. <i>Lean Manufacturing</i> says to eliminate mistakes in the development process. In other words we must look at how to remove mistakes in the requirements.<br />
<br />
By applying <i>Lean Manufacturing</i> principles to software development we must try harder to get the requirements right the first time. This is intended to avoid the enormous waste caused by repeatedly changing the design and the code. But this idea of <b><i>BDUF</i></b> is now generally regarded as futile.<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 280px;">
<div style="text-align: center;">
<b><span style="font-size: x-small;">BDUF? </span></b></div>
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">BDUF stands for <b><i>Big Design Up Front</i></b> and is the name given by Agilists for the way that software is normally developed using waterfall methodology. </span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">Decades of experience and studies have shown that, no matter how much effort is put into the initial design, there will be a disparity between what users need and what the software actually does.</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">I discussed this recently in <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank"><span style="color: blue;">Agile Design</span></a>.</span></div>
<span style="color: #3d85c6; font-size: large;">Agile Software Development</span><br />
<br />
Agile takes the opposite approach to that of <i>Lean Manufacturing</i>. The assumption is that you can never get the requirements right the first time. There will always be mistakes.<br />
<br />
The Agile approach is to start with the very basics of what you know, creating a minimal working initial version and then evolve the design based on feedback.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Software Development vs Manufacturing</span><br />
<br />
Lean tries to take ideas from a manufacturing process and apply it to the software development process. However, these processes are very different - eg:<br />
<ul>
<li>Manufacturing is about making many identical copies of a product. Every software product is different.</li>
<li>Manufacturing involves a repetitive process. Although there is some repetition in software development many things are unique to a project.</li>
<li>Eliminating even a small waste in manufacturing can make a large cost saving. The cost of eliminating waste in the software development process often outweighs the saving.</li>
</ul>
It should not be assumed that principles beneficially applied to manufacturing are similarly beneficial to the software development process.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Software Development vs Engineering</span><br />
<br />
OK, software development is not like manufacturing, but isn't it like the design as opposed to the manufacture of products?<br />
<br />
On the surface, this argument seems much more reasonable than the one above. A software developer is just another type of engineer; just as a civil engineer designs bridges or an aeronautical engineer designs planes, so a software engineer designs programs.<br />
<br />
This is getting a bit off track but it seems relevant to clarify this here. Creating software is <b>not</b> like creating physical objects. There are important reasons when designing physical objects to get a whole lot of things right up front. For example, you don't want to be almost finished as skyscraper when you realise the foundations are inadequate. Software does not suffer (as much) from these sort of limitations and so can be easily evolved as required (subject to use of Agile practices such as Unit Tests). I discussed this at length in the <b><span style="color: #3d85c6;">Software is Different</span></b> section of <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank"><span style="color: blue;">Agile Design</span></a>.<br />
<br />
The thing to remember: software developers are not engineers. The idea of "software engineering" has bugged me for many years and I will probably write about it in this blog soon.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Similarities</span><br />
<br />
I should be clear that the QA (and Lean) share a lot in common with Agile. I touched on this in <a href="http://devmethodologies.blogspot.com.au/2012/07/sqa-and-agile-methodologies.html" target="_blank"><span style="color: blue;">SQA and Agile Methodologies</span></a>. Some examples are:<br />
<ul>
<li>emphasis on JIT and deciding as late as possible</li>
<li>customer focus</li>
<li>automation of repetitive tasks</li>
<li>retrospectives and continuous improvement</li>
<li>importance of visibility of the process</li>
<li>quality is everyone's responsibility</li>
<li>empowering workers to make decisions</li>
<li>emphasis on training and learning</li>
</ul>
Despite that I do not believe some of the QA ideas typified by slogans such a "Right First Time" and "Quality Is Free" are always applicable. I might discuss this further in the future.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Conclusion</span><br />
<br />
The first principle of <i>Lean Manufacturing</i> is to <b>eliminate waste</b>. This has been shown to work well for manufacturing. For a repetitive process designed to mass produce identical products, eliminating even the smallest waste can produce large savings.<br />
<br />
However, this principle of <i>Lean Manufacturing</i> cannot be applied to the software development process. Every software project is different. The main type of "waste" that traditionally (and still commonly) occurs in software development is due to rework (of the design and the code) due to the requirements. To eliminate this waste the Lean philosophy says to improve the process - in other words try harder to get the requirements right from the start.<br />
<br />
Agile takes the opposite tack. We start with the minimum requirements needed to get something working and evolve the design based on responsive feedback. In effect, Agile methods (especially Unit Tests) provide a means to deal with the "waste" in a far simpler and less costly manner than trying to eliminate it. This waste in unavoidable and trying to eliminate it is counter-productive.<br />
<br />
This is not to say that Lean does not have anything to offer the software industry. In fact most of the principles of Lean are also shared by Agile. Even the philosophy of eliminating waste can be usefully applied to many areas of software development. But at their heart Lean and Agile are diametrically opposed.<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com1tag:blogger.com,1999:blog-7237530825191390698.post-71688083759275120892015-01-12T08:00:00.004+11:002015-01-15T16:22:11.209+11:00Vendor MentalityLast week I talked about <b><i>production line mentality</i></b>. Now it's time to consider <b><i>vendor mentality</i></b>.<br />
<br />
How are they related? In essence:<br />
<div style="text-align: left;">
</div>
<ul>
<li><b><i>production line mentality</i></b> - I just do what the boss/job spec. says</li>
<li><b><i>vendor mentality</i></b> - I just provide what the customer asks for</li>
</ul>
<div>
<br /></div>
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="color: #666666; font-size: x-small;">Note that I did <i>not</i> invent the term <b><i>vendor mentality</i></b> (though I <i>did</i> make up the term <b><i>production line mentality</i></b>).</span><br />
<span style="color: #666666;"><span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">It is apparently a well-known effect to which I was first introduced by a colleague - thankyou Rixt.</span></span></div>
<span style="color: #3d85c6; font-size: large;">Vendor Mentality in Developers</span><br />
<br />
In the software industry many developers and contractors suffer from <b><i>vendor mentality</i></b>. It is based on this simplistic approach: the client says what they want, the "software vendor" creates the software and the client pays for it. This works fine for (simple) manufactured goods. Creating software is usually much more involved than simply exchanging money for a product.<br />
<br />
Here are some reasons:<br />
<ul>
<li>the customer rarely knows exactly what they want</li>
<li>when the customer knows what they want, it may not be what they need</li>
<li>a customer will often specify what they see as the solution without really defining the problem or their objective</li>
<li>different customer representatives will have different understandings of requirements</li>
<li>what the customer wants will change as they understand their real objectives</li>
<li>what the customer wants will change due to external factors</li>
<li>what the customer wants will evolve as they try the software</li>
<li>what the customer wants can often change for no apparent reason</li>
</ul>
<br />
<span style="color: #3d85c6; font-size: large;">Vendor Mentality in Clients</span><br />
<br />
Clients and customers can also suffer from <b><i>vendor mentality</i></b> - <i>"just give me what I want"</i>. However, in my experience clients are far more amenable to feedback, negotiation and looking at the problem from a different perspective than developers believe. I have already discussed this problem on the customer side (see <a href="http://devmethodologies.blogspot.com.au/2013/09/customer-management.html" target="_blank"><span style="color: blue;">Customer Management</span></a>) - which details how and why you need to educate your client if they have a tendency towards <i><b>vendor mentality</b></i>.<br />
<br />
<span style="color: #3d85c6; font-size: large;">The Developer/Client Relationship</span><br />
<br />
To overcome this problem both sides need to work together to establish a partnership rather than consider it a simple buyer/seller relationship.<br />
<ul>
<li>developers need to ask questions rather than just take requests at face value</li>
<li>developers need to understand the business of the customer</li>
<li>developers often need to consider the customer's customer (see <b><span style="color: #3d85c6;">The Customer's Customer</span></b> in <a href="http://devmethodologies.blogspot.com.au/2013/09/customer-management.html" target="_blank"><span style="color: blue;">Customer Management</span></a>)</li>
<li>developers should not be afraid to say no to the customer</li>
<li>developers should identify ways to be of value to the customer</li>
<li>the customer needs a better understanding of the development process</li>
<li>the customer needs to actively guide the developers (via product owner)</li>
<li>the customer needs to be open about their problems and objectives</li>
<li>both parties should be honest and open with each other</li>
<li>both work together to come up with the most satisfactory solution</li>
</ul>
<br />
<span style="color: #3d85c6; font-size: large;">When Things Go Wrong...</span><br />
<br />
Mistakes happen. A great indicator of the health of the relationship between a software supplier and their client is what happens when things go awry. In an unhealthy relationship a supplier will try to cover up their mistakes, or (if that is not possible) excuses will fly or attempts made to shift the blame elsewhere. On the other hand, mistakes by the client are often not pointed out and the price is grudgingly born by the supplier.<br />
<br />
This situation is commonly attributed to a difficult customer. Indeed, the customer's representatives may make unreasonable demands, but this is usually due a lack of understanding on their part. First, they may not appreciate the difficulties of the development process. More often the problem arises due to a customer who does not really know what they want. In this case you need to clarify, for everybody's sake, exactly what they are trying to achieve.<br />
<br />
However, rather than the customer it is more often the developers, and particularly managers, that suffers from <b><i>vendor mentality</i></b>. They will insist on staff bending over backwards to accommodate the client, and do anything to prevent the company (particularly themselves) from looking bad. In such a <b><i>blaming culture</i></b> mistakes are punished which results in a large amount of effort spent in trying to deflect blame and in trying to avoid getting caught up in other people's problems.<br />
<br />
Better than adopting a <b><i>vendor mentality</i></b> (and trying to cover up mistakes or deflect blame) is to be open and honest with your customers. They (even large companies) are almost always less demanding and overbearing than their suppliers believe, especially when they fully understand the situation. It may be up to you, as the developer, to help them to fully understand the situation as already discussed. But if a customer cannot accept what you tell them and insist then you may be better off without them.<br />
<br />
A major problem is that many developers do not have the skills and personality to effectively interact with customers. They may be afraid to question the client and point out mistakes in their thinking. This is exacerbated in a culture of fear which does not encourage risk taking.<br />
<br />
Sometimes it takes courage to do what is right but in the long-term the customer will thank you. Here are some examples of what you as a developer can do:<br />
<ul>
<li>never agree to unrealistic deadlines</li>
<li>never agree to take on too many projects at the same time</li>
<li>never take a request at face value - ask more questions</li>
<li>if what the customer is asking for makes no sense then try to ascertain their objectives (see below)</li>
<li>simply say no if it is not in the interests of the customer (or the customer's customer)</li>
<li>don't be afraid to tell the client of their mistakes</li>
<li>admit your own mistakes</li>
</ul>
<br />
<span style="color: #3d85c6; font-size: large;">5 Whys</span><br />
<br />
OK, so how do you handle a client that asks for a software modification that makes no sense? Often a client will state exactly how they think the software should work, making many assumptions. Developers need to look beyond the request and ascertain the client's objectives. A particularly good technique I have found to arrive at the root cause of a problem is the <a href="http://en.wikipedia.org/wiki/5_Whys" target="_blank"><span style="color: blue;">5 Whys technique</span></a>. (Thankyou <b>Inbar</b> for introducing me to this technique!)<br />
<br />
The <b><i>5 Whys</i></b> technique simply says to ask "Why" to the initial request then to the subsequent answers until you can get no further. You can typically ask "Why?" up to five times (possibly more or less) before you get to the root cause of the problem.<br />
<br />
Consider this example (where C stands for client or customer and D stands for developer):<br />
<br />
<div style="background-color: #f0f0f0; padding: 16px;">
<span style="color: blue;">C: We want to ask and record why the operator has chosen the recovery operation.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because operators are selecting the operation when it is inappropriate.</span><br />
<span style="color: #cc0000;">D: Why</span>?<br />
<span style="color: blue;">C: Because they do not understand its purpose.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because they have not been trained on its use.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: We don't have time to give all operators training before they use the software.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because training is expensive and we only have courses twice a year.</span><br />
<span style="color: #cc0000;">D: I understand. An alternative would be to move the "recovery operation" to the supervisor menu so only experienced users can select it. This assumes that all supervisors have been trained and understand its purpose.</span><br />
<span style="color: blue;">C: Yes, all supervisors have undergone training. That sounds like a great idea!</span></div>
<br />
Despite its usefulness there are things to watch out for. If you use the technique on a
different client representative or group (or even the same representative at a different
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 230px;">
<div style="text-align: center;">
<b><span style="font-size: x-small;">The Wrong Approach :) </span></b></div>
<span style="font-size: x-small;"><br /></span>
<span style="color: blue; font-size: x-small;">C: I would like you to launch off a surface and into the air by using the muscles in your legs and feet.</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="color: #cc0000; font-size: x-small;">D: What vertical dimensionality do you require?</span></div>
time) you may get a completely different result. In my experience, it is quite surprising that a different set of answers, taking a completely different tack, often come to the same conclusion.<br />
<br />
However, occasionally you can follow a different path and come to a completely different root cause. Of course, this is actually a good thing as it allows you to find different approaches to a problem, or even completely different problems.<br />
<br />
Often asking the <b><i>5 Whys</i></b> can reveal flaws in the client's understanding. The previous example may have instead gone like this:<br />
<br />
<div style="background-color: #f0f0f0; padding: 16px;">
<span style="color: blue;">C: We want to ask and record why the operator has chosen a recovery operation.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because operators are selecting the operation when it is inappropriate.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because it is too easy to select the operation.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because it is presented as the first option on the sign-in menu.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: Because that is the obvious place to put it.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: We don't want people to sign in and use the system in a bad state.</span><br />
<span style="color: #cc0000;">D: Why?</span><br />
<span style="color: blue;">C: That causes data corruption whence we have to restore the previous day's database.</span><br />
<span style="color: #cc0000;">D: That is not the purpose of the "recovery". How often do you have to restore the database?</span><br />
<span style="color: blue;">C: It has recently been happening almost daily - on average once every 4 months per site.</span><br />
<span style="color: #cc0000;">D: We need to look into the reason for this!</span></div>
<br />
<span style="color: #3d85c6; font-size: large;">Conclusion</span><br />
<br />
As a developer you need to work with your customer(s) to find out what they are trying to achieve. Ask questions, take an interest in their business, and try to see things from their point of view (or even <i>their</i> customer's point of view - see <b><span style="color: #3d85c6;">The Customer's Customer</span></b> in <a href="http://devmethodologies.blogspot.com.au/2013/09/customer-management.html" target="_blank"><span style="color: blue;">Customer Management</span></a>).<br />
<br />
Don't let the customer dictate the solution to a problem. Hopefully, you are much more familiar with different techniques and technologies, as well as any technical limitations. On the other hand, you may need to understand more about the customer's business in order to choose the best solution.<br />
<br />
Conversely, the customer needs to better understand the development process (see <b><span style="color: #3d85c6;">What Every Customer Should Know</span></b> in <a href="http://devmethodologies.blogspot.com.au/2013/09/customer-management.html" target="_blank"><span style="color: blue;">Customer Management</span></a>). Some customers may need persuading to work with you in a partnership, but you will probably be surprised how amenable most customers are to developing a mutually beneficial relationship with their suppliers.<br />
<br />
Above all, be frank with the customer, even at the risk of offending them (for example, by pointing out their mistakes due to lack of understanding). Of course, this should be handled tactfully, but it is in everyone's best interests to ensure the customer understands the truth.<br />
<br />
Equally, you should not hide your own mistakes. This will help to build a relationship based on trust and mutual respect. <span style="color: #990000;"><b>All parties should be honest and open to work together to come up with the most satisfactory solution.</b></span><br />
<div>
<br /></div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-22653940379096380392014-12-31T16:20:00.000+11:002015-01-12T08:10:27.409+11:00Production Line Mentality (and Silo Syndrome)At the start of this month I mentioned, in passing, what I called <b><i>Production Line Mentality</i></b>. This is the propensity for individuals working in a large organization to concentrate solely on what they have been told to do, ie, their "job specification". This behavior is promulgated by a multi-layered, controlling management structure.<br />
<br />
Two people pointed out that what I was describing already had a name - <b><i>Functional Silo Syndrome</i></b> or simply <b><i>Silo Syndrome</i></b> - a term ascribed to <b>Phil Ensor</b>. Though <i>Production Line Mentality</i> and <i>Silo Syndrome</i> are very similar I don't believe they are exactly the same as I discuss later.<br />
<br />
Since the discussion of <i>Production Line Mentality</i> created so much interest I thought I should elucidate and mention a few things that I did not have room for last time. Later on I will talk about how the Agile approach addresses it.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Production Line Deficiencies</span></b><br />
<br />
Some say the production line is the most important invention of the industrial revolution. However, it has well-documented problems such as being boring, demoralizing, demeaning and, if the truth be known, tends to generate product of low quality. Luckily, in manufacturing the traditional production line has almost vanished in the last few decades due to studies (eg, see next) demonstrating better approaches. Unfortunately, in the software industry elements of the production line remain.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmaw2HgUDvxQU8BZ3insYy4xe9VCgXrr9FD7kXta3SOO7sTkKQBtxGLq3EHKxuoX3dBMpCJS1uhUlgWqlJgMrwGnb4rKJXnYYZ5Sl7sdhwlz_KdX3VIFwRRXZn63b2so2qz8SJl75QYCc/s1600/ProdLine4.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmaw2HgUDvxQU8BZ3insYy4xe9VCgXrr9FD7kXta3SOO7sTkKQBtxGLq3EHKxuoX3dBMpCJS1uhUlgWqlJgMrwGnb4rKJXnYYZ5Sl7sdhwlz_KdX3VIFwRRXZn63b2so2qz8SJl75QYCc/s1600/ProdLine4.jpg" height="240" width="320" /></a></div>
To show the problem, and the solution, I will first mention a study of a manufacturing production line. This occurred at a Swedish washing machine maker in the 1980's. The company switched one production line to a system where different teams assembled the machines from start to finish.<br />
<br />
Originally with a production line of about 20 people (six machines per day), they reorganized into four teams of five people. (Of course, there were costs involved in re-tooling, training etc.) Each worker was given the skills and knowledge to assemble a major component or even the whole machine.<br />
<br />
In brief, they found that productivity quickly increased to about 7-8 machines per day (and even more over time). Morale improved and less supervision was needed as individuals were motivated to get the work done and even suggest improvements that boosted their own efficiency. Importantly, the product had a marked improvement in quality. There were many other documented advantages such as less conflict and much greater flexibility when someone was absent.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Production Line Mentality in Software</span></b><br />
<br />
OK, so the production line has problems, but what has that got to do with software development? Actually, quite a lot.<br />
<br />
First, many developers are quite happy to potter along on their own problem with little or no interaction with others. By focusing on a small narrow task they lose sight of the bigger picture. To be productive all team members need to communicate and understand the organization's objectives.<br />
<br />
Second, traditional software development methodologies encourage this behavior The Waterfall model divides the development process into a series of phases (much like a production line). The work is divided into specialized areas: business analysts, system analysts, designers, coders, various flavors of testers, technical writers, etc.<br />
<br />
Finally, many large IT organizations are placed under a large amount of pressure by senior management. This often leads to a blaming culture and a controlling management style which is probably the largest contributing factor, as I discuss below.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Silo Syndrome</span></b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMlVBlvhyphenhyphen9qVIwlSLveEars7Q3seIeHMyeK3gXHF2ItITt_Iw22li-uIwSBrKOUAKluEKxM_6aRfOM8h-FRt2ccjbP-duPJDD8gqOKS1kHWpXCswqdS467YSf_1ZpY8XzbANbajxp-BKs/s1600/Silo1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMlVBlvhyphenhyphen9qVIwlSLveEars7Q3seIeHMyeK3gXHF2ItITt_Iw22li-uIwSBrKOUAKluEKxM_6aRfOM8h-FRt2ccjbP-duPJDD8gqOKS1kHWpXCswqdS467YSf_1ZpY8XzbANbajxp-BKs/s1600/Silo1.jpg" height="154" width="320" /></a></div>
<br />
Although the <i>Silo Syndrome</i> has essentially the same causes and effects as the <i>production line mentality</i> it is usually described in terms of the behavior of departments or "groups" within a larger organization rather than individuals. In the interests of self-preservation a group becomes protectionist of their knowledge and uncooperative with other parts of the organization.<br />
<br />
The original article on <b><i>Functional Silo Syndrome</i></b> by Phil Ensor beautifully explains this (see <a href="http://www.ame.org/sites/default/files/documents/88q1a3.pdf" target="_blank"><span style="color: blue;">Functional Silo Syndrome</span></a>). The following discussion of causes and effects of <i>production line mentality</i> generally also apply to the <i>silo syndrome</i>.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">How Does It Happen?</span></b><br />
<br />
The behavior starts as a response to an autocratic, controlling management style. As a defense mechanism the individual (or group) withdraws from any activity that involves risk. Some also restrict access to information, since knowledge is power. Of course, this is detrimental to the organization as a whole by stifling creativity, knowledge sharing, and collaboration.<br />
<br />
There are many reasons for this poor management style. It could simply be due to an individual manager. More often it is due to the culture of the organization -- coming from the top. Autocratic managers are generally attracted to an organization with such a culture (but they can pop-up anywhere).<br />
<br />
I can think of a few different scenarios:<br />
<br />
<b><span style="color: #3d85c6;">Egotism</span></b><br />
<br />
A common problem is a technically gifted individual who has been promoted to a position of power and attempts to micromanage all subordinates. Often they believe they know better than anyone working for them how to do the work. They only have people working for them because they don't have enough time to do everything themselves.<br />
<br />
Their enormous ego leads them to believe it, but they generally do <i><b>not</b></i> know better than those actually doing the work. Even if it were true it is still demoralizing and demeaning to be micromanaged in this way.<br />
<br />
<b><span style="color: #3d85c6;">Insecurity</span></b><br />
<br />
A related problem is a manager that is insecure in their own ability. Surprisingly this may occur in concert with the above since the manager may project confidence but are worried that eventually others will see through the façade. By controlling information they can more easily cover up their mistakes or find someone to blame.<br />
<br />
<b><span style="color: #3d85c6;">Self-preservation</span></b><br />
<br />
One of the most basic instincts is for self-preservation. If a manager gives up control then their role may be seen to be less important or even redundant. By embedding themselves in the work processes they make themselves an essential cog of the machine. Also, as we saw above, an insecure manager tightly controls information to hide their own ineptitude.<br />
<br />
This is perhaps the biggest impediment to addressing the problem. In a top-down, authoritarian structure, many layers of management are required to monitor and control everyone. If the people who actually do the work are empowered to make decisions then many of the layers can be reduced or even eliminated. Unsurprisingly, there is a huge amount of resistance to this sort of change.<br />
<br />
<b><span style="color: #3d85c6;">Transference</span></b><br />
<br />
If a culture of fear emanates from the top then it will permeate the entire organization. There is no advantage, and significant disadvantage and difficulty, in treating your staff well if you are treated badly yourself. In other words a manager cannot empower their subordinates if they are not themselves empowered.<br />
<br />
<b><span style="color: #3d85c6;">Megalomania</span></b><br />
<br />
It is rare but some managers simply enjoy wielding power to the point that it is almost sadistic. Luckily, I have only ever encountered one such manager who would deliberately inconvenience or even humiliate those that worked for him.<br />
<br />
<b><span style="color: #3d85c6;">Ignorance</span></b><br />
<br />
Finally, there are those managers who don't know any better. Either, they are inexperienced and are following the lead of others or this is the way they have always worked and are not open to any other options.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">How Does It Work?</span></b><br />
<br />
In most organizations, production line mentality results in a large hierarchical management structure. Each manager is given strict control of a group which is split into sub-groups each with their own manager, and so on. This hierarchy can contain many layers until you get down to the people at the bottom, who actually do the work.<br />
<br />
Information flows vertically. If you need information from someone in another section this is done through your supervisor. Information is distributed by a manager on a "need to know" basis.<br />
<br />
Rewards are doled out by management based on the perceived value of each individual. Inevitably this fosters competition and rivalry, which kills any sort of collaborative spirit. Individuals expend effort making themselves look good (and even try to make their co-workers look bad) to their boss, rather than focusing on the goals of the organization.<br />
<br />
When something goes wrong it's easy to point the finger at the person responsible. However, the root cause of the problem is usually that the person who made the mistake was not given enough information or assistance to do their job properly.<br />
<br />
Negative reinforcement (ie, punishment for mistakes) is the primary motivator, rather than positive reinforcement. This leads to an aversion to risk where nobody wants to take responsibility for anything beyond their small area of influence.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Indicators</span></b><br />
<br />
Many people working in this sort of environment are not even aware of it or just accept it. This is often because they have have never worked for a more enlightened company. Here are some possible clues based on the work environment:<br />
<ul>
<li> there are more chiefs than Indians - ie more managers than workers</li>
<li> monetary rewards are given based on individual performance reviews</li>
<li> each position has a detailed written job description</li>
<li> you often have to sign legal documents such as non-disclosure agreements</li>
<li> requirements documents must be signed off by several people</li>
<li> developers are not allowed to talk to customer representatives</li>
</ul>
Here are some clues that your boss is the problem:<br />
<ul>
<li> you don't really know what your boss does</li>
<li> you can never find your boss or arrange a meeting</li>
<li> you are not given enough information to do your work properly</li>
<li> you have to ask for a (deserved) pay rise</li>
<li> you cannot send emails to the client without clearing it with your boss</li>
<li> your boss threatens to fire you when you express any sort of dissent</li>
<li> you get into trouble for swapping tasks with a co-worker</li>
<li> when you book a meeting with your boss she postpones or is late</li>
<li> if your boss books a meeting with you and you are late she hits the roof</li>
<li> all emails you send must be CC'd to your boss</li>
<li> you cover up a problem rather than tell your boss</li>
<li> you discover there was a meeting (on a subject crucial to your work) to which you were not invited</li>
<li> you are asked to work overtime when there is no reason to do so</li>
<li> your boss keeps reminding you about the poor job market</li>
<li> your boss never admits they made a mistake</li>
<li> your boss keeps reminding you of your own past mistakes</li>
</ul>
Here are a few general clues about an organization with a poor culture:<br />
<ul>
<li> you have never met anyone who uses the software that you write</li>
<li> everyone knows about a problem that needs fixing but nobody is willing to tackle it</li>
<li> there is often conflict in the workplace</li>
<li> many problems occur - the same problems happen over and over</li>
<li> people in the organization have stress-related health problems</li>
<li> you are regularly given large design documents about projects you have never heard of</li>
<li> two developers discover that they have both fixed the same bug</li>
</ul>
If you are a boss, here are some clues that you might be the problem:<br />
<ul>
<li> you get the feeling that you don't know the full story about what is happening</li>
<li> the people who work for you show no initiative</li>
<li> the people who work for you are incompetent</li>
<li> the people who work for you are risk-averse</li>
<li> you don't know the name of everyone who works for you</li>
<li> there are people that you have not talked to in over a month</li>
<li> you have an "open door" policy but nobody takes advantage of it</li>
<li> the client asks for a simple change to which you give an estimate, but are shocked when the team cannot deliver</li>
</ul>
<div>
<br /></div>
<b><span style="color: #3d85c6; font-size: large;">Consequences</span></b><br />
<br />
By now I hope you are convinced of the detrimental effects of production line mentality (and silo syndrome). To reiterate it makes for an organization with little collaboration and creativity to solve problems. Insular thinking results in inefficiencies such as poor processes, redundant processes and bad decision making.<br />
<br />
The effect on morale results in poor employee engagement, absenteeism and sub-optimal productivity. Moreover, because managers build themselves into the system they become a single point of failure which affects flexibility and resilience.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Prevention</span></b><br />
<br />
So how do we prevent this from happening? The simplest way is to follow an Agile methodology. For example, in Scrum the team is self-organizing, so resist the urge to "help" them get organized. Another piece of good advice comes from XP (Extreme Programming) to "eliminate fear".<br />
<br />
The most important point is for managers to empower their charges. Don't assume they will get it wrong. If they don't do it the way you would do it, it may actually be a better way. If you trust people they will usually honor that trust.<br />
<br />
Some simple tips are<br />
<ul>
<li>encourage spontaneous feedback, eg don't react badly to a mistake or oversight.</li>
<li>reward the team rather than individual to encourage collaboration</li>
<li>eliminate formality & the need to "go through channels"</li>
<li>have more than an open door policy - go out and talk to people</li>
<li>use instant messaging - but also talk face to face sometimes</li>
<li>encourage people to interact as necessary with whoever they need to</li>
</ul>
<div>
<br /></div>
<b><span style="color: #3d85c6; font-size: large;">Does Scrum Promote Silos?</span></b><br />
<br />
Scrum is great for counteracting "production line mentality". Allowing the team to self-organize promotes interaction (within the team) which results in better organization, processes and products. It is also good for morale due to team members having a feeling of making a contribution and working together toward a common goal. In particular, the daily standup allows everyone to know what everyone else is doing, with improved coordination and less mistakes.<br />
<br />
But does Scrum inhibit collaboration <i>between</i> teams? The simple answer is - it shouldn't but it can.<br />
<br />
When different groups do not collaborate this is known as the "silo syndrome" as we saw above. Sometimes Scrum teams have this problem due to a misunderstanding of the roles on the product owner and scrum master. Let's first look at the problems these roles are designed to overcome.<br />
<br />
<b><span style="color: #3d85c6;">Product Owner</span></b><br />
<br />
Even in (or especially in) an open, collaborative environment there can be a problem of conflicting and volatile requirements. There are often many people (users and other client representatives, managers, business analysts, etc) with input into how the software is to be modified. One manager might insist on all bugs being fixed as a high priority, another might want to sneak in their favorite feature or improve an existing feature -- you have probably seen this sort of thing yourself. Different people have different ideas and priorities; and these ideas and priorities tend to change often.<br />
<br />
In Scrum, having a product owner and sprint backlog avoids this problem by having all requirements come through one person. This ensures that the developers are not pulled in many different directions at once. Further, because the sprint backlog is unchanging they know that things will not suddenly change, at least until the end of the sprint.<br />
<br />
However, having a product owner does not in any way preclude the team from talking to people outside the team. In fact this sort of collaboration is encouraged. It simply means that all requirements come through the PO and are prioritized in the backlog.<br />
<br />
<b><span style="color: #3d85c6;">Scrum Master</span></b><br />
<br />
The scrum master is in many ways an interface between the team and higher-level management. The main task of the scrum master, outside the team, is to remove roadblocks. This involves them using their influence to obtain resources, help or information. Some scrum masters take it upon themselves to intercept interference from outside the team, such as a senior manager who wants to control the team. Their are always managers who think they can organize the team better than it can organize itself.<br />
<br />
In summary, an over-zealous scrum master can turn a scrum team into a "silo".<br />
<br />
Finally, a Scrum Team can be unfairly perceived as a silo. A team should be composed of all the persons required to accomplish their tasks from start to finish. This means that they may not require a lot of communication with people outside the team.<br />
<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Conclusion</span></b><br />
<br />
<i>Production line mentality</i> (and <i>silo syndrome</i>) begins with a culture where personal interest (or the interests of a group within the organization) is not aligned with the organization's best interests. Fear prevails and individuals are driven by self-protection (or protection of their department) rather than desire to do the best for the organization as a whole.<br />
<br />
This culture is characterized by many layers of bureaucracy which is a classic example of the <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE</span></a> principle. Employees show no initiative and just wait to be told what to do. Risk-taking is discouraged since mistakes are punished.<br />
<br />
The solution to this problem is to empower employees to take control of their own destiny. Encourage collaboration and discourage rivalry by rewarding the team and not individuals. Share the vision of the organization so that everyone is working towards the same end.<br />
<br />
Generally, following the ideas behind Agile will encourage collaboration and work against the <i>production line mentality</i> (and <i>silo syndrome</i>).<br />
<br />
[Note: I was also going to talk about the closely related problem of <b><i>vendor mentality</i></b>, but that will have to wait for next week.]<br />
<div>
<br /></div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0tag:blogger.com,1999:blog-7237530825191390698.post-13904069186039751612014-12-01T11:40:00.000+11:002015-01-08T17:21:49.565+11:00Agile RolesBack in May I wrote about how software design is done in Agile. I received some feedback which I promised to respond to in a future post (this one). Sorry for the delay.<br />
<br />
Someone asked about the role of designers in Agile. They thought I was implying that specialist designers were not needed. Well, just to be clear, I will say it outright: <i>No dedicated designers!</i> All or most of the team should be involved in the design though typically some will have more input than others.<br />
<br />
<div style="float: right; line-height: 24px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #134f5c; font-family: Georgia, Times New Roman, serif; font-size: large;">
"No dedicated designers!"</span></div>
When moving to Scrum people who just do "design" need to stop it. Designers traditionally are either technical (sometimes called architects) or business-oriented (sometimes called analyst/designers). I talk below about how these (and other) roles may change when moving to agile but in brief designers can move in two different directions - either to more development work or to more of a PO type role. Architects often become more hands-on - spending more time coding and reviewing. Analyst/designers can move back to development or if not from a technical background will need to move into a role involving mostly acceptance testing and customer interaction.<br />
<br />
Another comment was: "If design, programming (and testing) are to be done together then should they all be done by the same person?" In essence: <b><span style="color: #cc0000;">YES</span></b>. But before I get into that I need to talk a little about roles in Agile teams.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Multi-skilled Teams</b></span><br />
<br />
Everyone agrees that Agile development uses multi-skilled (or cross-functional) teams. The problem is nobody really agrees (or even pretends to know) exactly what that means. Does it mean each of the team members have the skills to do all, or at least many, of the required tasks? Or does it mean that altogether the team has the required skills but each specializes in their own skill-set?<br />
<br />
In my experience most Agile "experts" use the latter definition. For example, I was recently involved in the implementation of Scrum in a large company, and one of the things that the Scrum consultants emphasized is that a Scrum team (ie, "pigs" not "chickens") is made up of members with a wide variety of skills. However, I get the strong impression that this is mainly to placate those employees who feel that they may be redundant in the new order of things.<br />
<br />
In reality, in an organization suffering from <b><i>production line mentality</i></b> (see below) adoption of an Agile methodology will mean that there will be less need for some existing roles. Less BDUF (see my <a href="http://devmethodologies.blogspot.com.au/2014/05/agile-design.html" target="_blank">post on <span style="color: blue;">Agile Design</span></a>) means that there is no need for dedicated designers as design is performed continuously by the developers. Also, developers take more responsibility for testing so there is less need for dedicated testers doing black-box testing (like regression tests). This means that developers have more responsibilities (rather than just coding), but this is a good thing as it promotes DIRE (see <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank">DIRE</a>) but also makes the work more rewarding and interesting.<br />
<br />
If you need less people for other roles, such as designers, does this mean you need more developers? The simple answer is no. In my experience the same developers can actually be more productive, so you may even need less developers too!<br />
<br />
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 240px;">
<span style="font-size: x-small;"><b>Here I should note that I am talking about using Scrum in a pure software development environment.<br />
<br />
I know that Scrum has been used successfully in other environments and that is great. However, whatever the environment all team members must have enough shared context to understand what everyone else in the team is doing.
</b></span></div>
<span style="color: #3d85c6; font-size: large;"><b>Scrum Team Composition</b></span><br />
<br />
Ideally all members of a Scrum team should be developers. That is, team members (apart from the Product Owner and perhaps the Scrum Master) should have the ability to write code. To understand why I will first recap on the advantages of Scrum.<br />
<br />
Scrum (and Agile in general) has many benefits such as promoting team-work, working towards a common goal, quick response to change, etc. This is achieved by good communication and empowering the team to make their own decisions. The daily standup is particularly important as it allows everyone to know what everyone else is doing.<br />
<br />
When everyone in the team can (and does) understand what everyone else is doing this avoids issues like:<br />
<ul>
<li>differences in understanding of what is to be done</li>
<li>poor division of work</li>
<li>duplicating work - such as two developers fixing the same bug</li>
<li>forces pulling in different directions and introducing conflicting changes</li>
<li>not realizing when someone needs help</li>
<li>not being able to have someone else take over a task due to illness</li>
<li>not being able to have the whole team focus on a critical problem</li>
<li>inability to find another team member who understands what you are doing well enough to perform a review</li>
</ul>
Unless the team members are all developers they cannot really understand what everyone else in the team is doing (and how, why, etc). This is essential for Scrum to work (see <a href="http://devmethodologies.blogspot.com.au/2013/01/why-scrum-fails.html" target="_blank">Why Scrum Fails</a>).<br />
<br />
Of course, different individuals will have different levels of experience and different aptitudes. Over time, team members become familiar with each other's abilities. It is easy and natural for team members to take each other's skills into account when allocating tasks during the sprint planning.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Production Line Mentality</b></span><br />
<br />
The production line was a major invention in the history of industrialization, since even unskilled workers can become very good at a simple repetitive task. However, its drawbacks were quickly discovered. Workers suffer from frustration and alienation. Once a task is mastered boredom sets in and mistakes are made, even for simple things.<br />
<br />
Quality and productivity are greatly improved when workers are given a variety of challenging tasks. Performing different jobs as part of a small team working towards the same goal can be a tremendous motivator.<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="font-size: x-small;"><b>Another problem with production line mentality is that it usually results in post-production testing - ie someone inspecting the product coming off the end of the line. </b></span><br />
<span style="font-size: x-small;"><b><br /></b></span>
<span style="font-size: x-small;"><b>This sort of "Black-box testing" is not a good way to add quality particularly for software (see <a href="http://devmethodologies.blogspot.com.au/2013/11/unit-tests-white-box-testing.html" target="_blank"><span style="color: blue;">Unit Tests - White Box Testing</span></a>).</b></span></div>
<br />
What I call "Production Line Mentality" is where everybody has a specific well-defined job specification. This is common in an organization with a top-down management style where a worker's purpose is to impress their boss rather than work with others. In other words it does not encourage people to work together to accomplish their team's goals.<br />
<br />
It is caused by a controlling (rather than empowering) management style where each role is kept simple to be easily understood and hence controlled. However, it results in a large number of specialized positions and a multi-layered management structure to be able supervise everybody in the organization.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4ZnJAaQ63faB-1LgmPi9u8M71dvcxUwa3XFMUt4F5l1R0o-01UA5-CqtznsXywrTxbAa1qR0L_XnAdJjKxEt2BVSAm519NoFcCxV1j4ts86iKqUxVcKpU9ZTRnszVNl1gggV25qlU7dM/s1600/ProdLine1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4ZnJAaQ63faB-1LgmPi9u8M71dvcxUwa3XFMUt4F5l1R0o-01UA5-CqtznsXywrTxbAa1qR0L_XnAdJjKxEt2BVSAm519NoFcCxV1j4ts86iKqUxVcKpU9ZTRnszVNl1gggV25qlU7dM/s1600/ProdLine1.jpg" height="276" width="320" /></a></div>
This discussion actually ties in nicely with some of my recent posts. First, multi-layered management is a classic example of the <a href="http://devmethodologies.blogspot.com.au/2012/10/the-layer-anti-pattern.html" target="_blank"><span style="color: blue;">Layer Anti-Pattern</span></a> which is a pattern of bad software design which I have found can be applied in other domains.<br />
<br />
Moreover, these layers form an excellent example of the <a href="http://devmethodologies.blogspot.com.au/2014/04/dire.html" target="_blank"><span style="color: blue;">DIRE principle</span></a>. First, the managers at the top of the hierarchy are typically completely out of touch with the people actually doing the real work in the organization as they are isolated from them by all the layers. Perhaps even worse is that it encourages the workers themselves to concentrate on their own specific task without regard for the goals of the broader organization.<br />
<br />
In an Agile development environment the developers are empowered to do whatever they need to do (within their bounds) to finish their tasks by the end of the sprint. For a traditional controlling manager it may be hard to deal with an environment where you can't even understand what everyone is doing let alone control it.<br />
<br />
A controlling manager can be a real problem for the Agile approach. On the other hand, having developers who are happy to (or used to) being controlled like this is another major obstacle for the adoption of Agile. Years of manipulation (and even threats) means that many are happy simply to be given work as outlined in their job spec.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Traditional Roles</b></span><br />
<br />
Let's look at traditional roles and how they change in an Agile world.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Team Leader</span><br />
<br />
Scrum books simply say that the team leader role is no longer necessary. The team self-manages so the need for a manager within the team ceases to exist.<br />
<br />
I disagree with this. In fact most of the same books describe a role for the Scrum Master which is almost exactly what I have always thought a team leader should be. (Perhaps they like the different title to emphasize that many team leaders are using a bad style.)<br />
<br />
<b><span style="color: #cc0000;">The team leader is now called the Scrum Master.</span></b> Many team leaders also write code. That's OK too - you can have a part time scrum master who also codes.<br />
<br />
However, if you think a team leader/scrum master is there to tell the team members what to do, then forget it. One of the main advantages of Agile is that teams are self-organizing and self-managing (within the bounds set for them by the PO and higher management). Small self-organized teams generally work much more efficiently and harmoniously than "centrally-organized" teams.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Designer</span><br />
<br />
There is no longer any room for analysts/designers who spend weeks or months understanding a problem and trying (unsuccessfully, of course) to come up with the perfect, well-documented design. In an Agile world analysis and design is performed "just in time" (see <a href="http://devmethodologies.blogspot.com.au/2014/04/jit.html" target="_blank">JIT</a>). The developers design, code (and test) all at once. This is not to say that what is designed is left to the whim of the developers - in fact how the design evolves is more closely controlled through the customer representative (product owner).<br />
<br />
Traditional designers can move toward a role with industry knowledge, in particular how the software will help the business (or even the customers of the business). Perhaps they will be the actual PO (product owner), though I prefer someone even closer to the customer than that. Probably they will become a "business analyst" assisting the PO. Depending on the software (and despite the Agile preference of JIT design) there may be a need to mock up designs slightly ahead of time to garner feedback from the PO and/or customer.<br />
<br />
Alternatively, or also, they may also do a lot of <i>Acceptance Testing</i> (see below). Whatever they do, their main focus (as for any Scrum team member) should be on completing the sprint backlog before the end of the current sprint.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Architect</span><br />
<br />
There are just two points I want to mention about software architects using quotes from the excellent book <b><i>97 Things Every Software Architect Should Know</i></b>.<br />
<blockquote class="tr_bq">
" [the architect] should not sit in an ivory tower dictating the way forward but should be on the ground working with the team "</blockquote>
- from 19. <b>Architects must be hands on</b> by John Davies<br />
<blockquote class="tr_bq">
"As well as being prone to incidental complexity and inertia, designing large systems upfront means larger projects, which are more likely to fail, more likely to be un-testable, more likely to be fragile, more likely to have unneeded and unused parts, more likely to be expensive, and more likely to have a negative political dimension. ...</blockquote>
<blockquote class="tr_bq">
"Design the smallest system you can, help deliver it, and let it evolve towards the grand vision. Although this might feel like giving up control, or even shirking your responsibilities, ultimately your stakeholders will thank you for it."</blockquote>
- from 97. <b>Great software is not built, it is grown</b> by Bill de hOra.<br />
<br />
In brief: architects work with the team to evolve the design, spending most of their time coding and reviewing.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Programmer</span><br />
<br />
In an Agile environment programmers now do everything that is required of the team (analyze, design, code, test, etc). They do whatever it takes to complete the sprint tasks by the end of the sprint.<br />
<br />
This is in stark contrast with some traditional environments where programmers have just been coders - they take a design from the analyst/designer and code it for "QA" to test. This is demeaning for programmers who are usually capable of a lot more. Even if you care not for the morale of developers giving the programmers free reign to think about the design and even experiment at little will produce a much better design than any analyst/designer (no matter how clever) can invent in their head.<br />
<br />
Of course, this does not mean the programmers can do whatever they want. They are closely guided by the product owner who, after all, prioritizes the backlog effectively deciding on the sprint task(s) that are the focus for the team.<br />
<br />
<span style="color: #3d85c6; font-size: large;">Tester</span><br />
<br />
If waterfall development is disempowering to programmers it is much worse for testers. As compensation, testers are often given the impressive title of quality assurance experts, despite the fact that quality assurance has little to do with testing.<br />
<br />
You may not believe this but using Agile development (especially <i>Unit Tests</i>) there is a greatly reduced need for dedicated testers. How great this reduction is depends to a large extent on how much testing the developers do already. At one extreme I recently worked in an environment where there were twice as many testers as developers! The software contractor had there own tester(s) who worked closely with the coders. Then the customer had several testers, plus an "offshore" test team to perform regression testing, as well as an automated testing team.<br />
<br />
There are many different names for the types of testing (and testers) that are used in the software industry. In Agile there is just two general types of testing:<br />
<br />
<ol>
<li><b><i>Unit Tests</i></b>: automated tests written by the developers of the code to test individual (low and high level) modules</li>
<li><b><i>Acceptance Tests</i></b>: performed by the PO, customers, or anyone who wants to try the software</li>
</ol>
<br />
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 200px;">
<span style="font-size: x-small;"><b>Note that Unit Tests are always automated, but acceptance tests may be automated too. Often the developers will add a simple scripting system to make it easy for the PO and others to create test scripts.</b></span><br />
<span style="font-size: x-small;"><b><br /></b></span>
<span style="font-size: x-small;"><b>This is useful for testing the current changes. But don't go overboard and add lots of tests for existing functionality as they will most likely fail when changes are made (and even act as a disincentive to change). Leave the regression testing to the Unit Tests.</b></span></div>
To understand this better consider the testing that an aircraft manufacturer does. First, individual parts are developed (or purchased). The developers of these parts (for example, spark plugs) will design, build and test them themselves and provide a hopefully reliable product. Some parts may be made from a combination of other lower-level parts, but it is still up to the developer of any part to thoroughly test it. Of course, larger, more complicated, parts may require more elaborate testing - testing of an aircraft engine may require a huge test rig. In the end it is always up to the maker of a part to ensure it performs to the requirements of the plane manufacturer. Testing of parts is the equivalent in software development of <i>Unit Testing</i>.<br />
<br />
When the first plane (or a prototype) is finally built it is then up to a test pilot to perform various flights and manoeuvres to ensure that the plane performs as expected. This is the equivalent in software development of <i>Acceptance Testing</i>. This analogy is not perfect though, since <i>Acceptance Testing</i> of software should usually be performed much earlier than test flights.<br />
<br />
If a Scrum team requires a dedicated tester at all then perhaps one or two members (at most) could be required for <i>Acceptance Testing</i> on behalf of the PO. They should spend much of their time understanding what the software is to do by discussing it with PO, business analyst, customer and any other stakeholders - something that an analyst/designer traditionally does. They might also attempt to automate much of their work using acceptance test scripts.<br />
<br />
Whatever, they do their main focus should be producing working software at the end of the sprint. This means giving the users what they need as opposed to testing for conformance to any written specification.<br />
<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>Conclusion</b></span><br />
<br />
If you are about to, or have been trying to, move toward an Agile development environment then you should ignore the advice given by many Agile coaches and experts that most roles will not change. There is no longer any need for software designers and less need for testers. Instead the whole team is involved in analysis, design, coding and testing - and this is all done "just in time" (see <a href="http://devmethodologies.blogspot.com.au/2014/04/jit.html" target="_blank"><span style="color: blue;">JIT</span></a>). (Of course, if they are willing to adapt a role can be found for anyone -- it may be more challenging but will probably involves better use of their abilities.)<br />
<br />
Most importantly, managers have less control of the team, which is now self-organizing. The major benefit is simply that a creative team can organize themselves much better than any manager. It also makes for a more rewarding and enjoyable working environment. The developers concentrate on creating good software and overcoming hurdles rather than making themselves look good for their annual performance review or trying to shift the blame when something goes wrong.<br />
<br />
It may be hard to overcome the unthinking production line mentality (I do what the boss tells me to do) or vendor mentality (I do what the customer tells me to do). But please try!<br />
<br />
<br />Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com6tag:blogger.com,1999:blog-7237530825191390698.post-63786029085171318052014-09-30T17:59:00.000+10:002014-10-09T13:02:30.089+11:00Agile's Fifth ElementYou have probably heard of the "Agile Manifesto". This was designed to enunciate Agile's fundamental approach by those who coined the term "Agile" software development (see <a href="http://agilemanifesto.org/" target="_blank"><span style="color: blue;">Agile Manifesto</span></a>).<br />
<ul>
<li><span style="color: #990000;"><b>Favor individuals and interactions over processes and tools</b></span></li>
<li><span style="color: #990000;"><b>Favor working software over comprehensive documentation</b></span></li>
<li><span style="color: #990000;"><b>Favor customer collaboration over contract negotiation</b></span></li>
<li><span style="color: #990000;"><b>Favor responding to change over following a plan</b></span></li>
</ul>
<div style="background-color: #dddddd; float: right; line-height: 14px; margin: 6px; padding: 6px; width: 250px;">
<span style="font-size: x-small;"><b>Elements, Principles, ???</b></span><br />
<span style="font-size: x-small;"><b><br /></b>I'm never sure what to call the Agile Manifesto's 4 main statements. They can't be principles as there are also 12 Agile Principles (see <a href="http://agilemanifesto.org/principles.html" target="_blank"><span style="color: blue;">Agile Principles</span></a>).</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">I have seen various names, such a guidelines, values or statements. I think <b><i>Elements </i></b>is the logical choice as it emphasizes their fundamental importance.
</span></div>
<div>
<br />
For a long time now I have felt there is one thing missing from the above. It is at least as important as a couple of them. I call this <b><i>Agile's Fifth Element</i></b>.<br />
<br />
<ul>
<li><span style="color: #990000;"><b>Favor simple design over reusability and generality</b></span></li>
</ul>
</div>
<div>
<br />
<b><span style="color: #3d85c6; font-size: large;">What is an Agile Element?</span></b><br />
<br />
To see why we it should be added to the other four we need to decide how a statement qualifies to be an <i>Agile Element</i>. In my opinion an Agile Element needs to:<br />
<ul>
<li>challenge, or at least de-emphasize, (previously accepted) best practice</li>
<li>be fundamental to the Agile approach</li>
<li>be important enough not to simply be considered an Agile Principle</li>
</ul>
There are many books on software project management typical of the Waterfall era (mainly written from the 1960's to the 1980's) that emphasize the importance of following strict procedures, having everything well-documented, and having a water-tight contract with the customer. Most of all they talk about the importance of planning a project down to the smallest detail.<br />
<br />
I won't go into why these ideas don't work (again), though the authors make them look very good on paper. Luckily Agile came along and turned all of this on its head. The four elements of the Agile Manifesto clearly highlight what was (and often still is) wrong with what was considered the correct way to develop software.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">How Does it Qualify as an Agile Element?</span></b><br />
<br />
Let's look at how the proposed fifth element satisfies the above criteria by looking at each criterion in turn.<br />
<br />
<div>
<div style="border-collapse: separate; border-spacing: 0px;">
<span style="font-family: Tahoma; text-align: -webkit-auto;"><span style="color: #3d85c6;"><b>Does it challenge accepted best practice?</b></span></span><br />
<br />
The big paradigm to come out of the 1980's was the emphasis on reusability. Many in the Agile world now think that this emphasis was a mistake as I previously explained in <a href="http://devmethodologies.blogspot.com.au/2012/11/reusability-futility.html"><span style="color: blue;">Reusability Futility</span></a>.<br />
<br />
In brief, experience has shown that too much software is designed to be flexible and reusable for no purpose. This leads to increased complexity to the detriment of other attributes such as understandability, verifiability, efficiency, etc. The worst effect is that software becomes harder to maintain and cannot adapt to change.<br />
<span style="font-family: Tahoma;"><br /></span>
<span style="color: #3d85c6; font-family: Tahoma;"><b>OK, but why is it fundamental to the Agile approach?</b></span><br />
<span style="font-family: Tahoma;"><br /></span>Keeping things simple is part of the agile approach. In fact the 10th Agile Principle says:<br />
<br /></div>
<div style="border-collapse: separate; border-spacing: 0px;">
<div style="text-align: center;">
<b><span style="color: #990000;">Simplicity -- the art of maximizing the amount of work not done -- is essential.</span></b> </div>
<br />
Simplicity is necessary in order to create small, frequent software releases - a major part of the Agile approach. Further, keeping things as simple as possible allows the software to more easily evolve, since unnecessary constraints interfere with continual refactoring -another fundamental feature of Agile development.<br />
<br />
<div style="float: right; line-height: 24px; padding: 16px; text-align: center; width: 250px;">
<span style="color: #3d85c6; font-family: Georgia, Times New Roman, serif; font-size: large;">
designing for flexibility<br />adds complexity</span></div>
Of course, you may ask: can't you design software to be both simple <i>and </i>flexible? Sometimes you can find a design that is simpler and more flexible than any alternative but usually there is a trade-off, particularly as modules become larger. The overwhelming general experience is that designing for flexibility adds unnecessary complexity.<br />
<div>
<span style="font-family: Tahoma; text-align: -webkit-auto;"> </span></div>
<span style="color: #3d85c6; font-family: Tahoma;"><b>Is it really important enough to be the Fifth Element rather than just a principle?</b></span><br />
<span style="font-family: Tahoma;"> </span><br />
<span style="text-align: -webkit-auto;">Yes, it is! It counters one of the biggest problems currently facing software development - the tendency of developers to over-design and add unnecessary code. There are lots of reasons this occurs such as:</span><br />
<br />
<ul>
<li><span style="text-align: -webkit-auto;">temptation to add something now which is "sure to be needed later"</span></li>
<li><span style="text-align: -webkit-auto;">desire to use some new design pattern that one has recently been read about</span></li>
<li><span style="text-align: -webkit-auto;">hope that a general purpose module can have use in other projects</span></li>
<li><span style="text-align: -webkit-auto;">use of particular new technology to have on your CV</span></li>
<li><span style="text-align: -webkit-auto;">desire to avoid future code modifications</span></li>
</ul>
<br />
<span style="text-align: -webkit-auto;">These reasons, and their consequences, are further elaborated in <a href="http://devmethodologies.blogspot.com.au/2013/12/the-gas-factory-anti-pattern.html" target="_blank"><span style="color: blue;">Gas Factory Anti-Pattern</span></a>.</span></div>
<div style="border-collapse: separate; border-spacing: 0px; font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
</div>
If you're still not convinced I recommend reading Chapter 18 of the excellent book <b><span style="color: #990000;">97 Things Every Software Architect Should Know</span></b>. It is written by Kevlin Henney and entitled <b>Simplicity Before Generality, Use Before Reuse</b>. It says exactly what I have been trying to get people to understand for many years.<br />
<div>
<br /></div>
<b><span style="color: #3d85c6; font-size: large;">Why Is It Missing?</span></b><br />
<br />
You would have to ask the authors of the Agile Manifesto why they left it out. I suspect that its importance was simply not appreciated at the time.<br />
<br />
I guess the first four elements highlight problems with best practice that have been promulgated since the 1960's. The proposed fifth element highlights the problem of something that only became considered best practice later (1980's) - that is designing software for reusability.<br />
<br />
Another theory is that many of the creators of the Agile Manifesto were heavily involved in OO (Object-Oriented) technologies. To de-emphasize reusability would be anathema to them, since reusability is a fundamental part of OO design.<br />
<br />
<span style="color: #3d85c6; font-size: large;"><b>A Different Fifth Element Proposal</b></span><br />
<br />
As I write this post I have discovered that our dear old friend Uncle Bob (Martin) has also proposed an additional element for the Agile Manifesto:<br />
<ul>
<li><span style="color: #990000;"><b>Favor craftsmanship over execution</b></span></li>
</ul>
In essence he is saying that many developers are only concerned with getting the code working without regard to the quality of the code they produce. I agree with Uncle Bob that this is a serious problem that affects much, if not most, software development.<br />
<br />
But Uncle Bob's proposal, though eminently worthwhile, does not qualify as an Agile Element for the reasons mentioned above (see <b><span style="color: #3d85c6;">What is an Agile Element?</span></b>).<br />
<br />
First, it does not question accepted best practice since software quality experts have been emphasizing the importance of various quality attributes of software (such as maintainability) for decades. I also do not believe it is fundamental to the Agile approach, though many Agile practices, which could be considered as promoting craftmanship (such as pair programming), will improve code quality.<br />
<br />
<b><span style="color: #3d85c6; font-size: large;">Summary</span></b><br />
<br />
My proposal is for an additional element to be added to the existing four elements of the Agile Manifesto. I consider this new element to be a least as important as a couple of the big four - personally I would rank it third. I believe it to be fundamental to the Agile approach as it is practiced today. For example, many practitioners of XP (<a href="http://en.wikipedia.org/wiki/Extreme_programming" target="_blank"><span style="color: blue;">Extreme Programming</span></a>) talk about the importance of YAGNI and simple design (see <a href="http://www.extremeprogramming.org/rules/simple.html" target="_blank"><span style="color: blue;">Simplicity is the Key</span></a>). Similarly in <a href="http://en.wikipedia.org/wiki/Scrum_(software_development)" target="_blank"><span style="color: blue;">Scrum</span></a>, developers focus on solving current customer needs by concentrating solely on the most important backlog items.<br />
<br />
<div style="float: right; line-height: 24px; padding: 16px; text-align: center; width: 200px;">
<span style="color: #3d85c6; font-family: Georgia, Times New Roman, serif;"><b>... software is designed<br />for general purpose<br />and, ironically,<br />ends up being fit<br />for nothing at all!</b></span></div>
The problem of unnecessary generality and reusability is largely unrecognized, but significant and growing. I believe it is mainly due to the training and mentality of developers, particularly software architects. Perhaps with the best intent, software is designed for general purpose and, ironically, ends up being fit for nothing at all!<br />
<br />
Far better is to start with a simple design that can be easily modified (with the assistance of Unit Tests) into whatever the future requires. Without the burden of unnecessary complexity the software may be able to evolve forever or at least not become a "legacy" application almost immediately as most software tends to do.<br />
<div>
<br /></div>
So do you think this is a worthwhile proposal? I would be interested to hear your comments.<br />
<br />
<br />
<br /></div>
Andrewhttp://www.blogger.com/profile/09583922517961948560noreply@blogger.com0