CSS 390: Notes from Lecture 2 (DRAFT)
Our Story So Far
-
this course is
all about that code
vs. a traditional software engineering course
-
implementation is where the rubber meets the road
-
not to say the topics covered there and elsewhere in the
programme aren't invaluable too: need the entire
powertrain
-
you're planning to do this for a living
-
4 questions raised by course title
-
what is engineering?
-
what is software?
-
what is software engineering?
-
what is tactical?
-
engineering
-
science to build stuff
-
best practices to build stuff
-
most importantly: understanding the tradeoffs to build stuff
-
software
-
more than just the code
-
large-scale, complex systems
-
these days, large-scale means distributed
-
continuous development ("maintenance")
-
iceberg principle: 90% of lifecycle costs occur in the
post-delivery "maintenance" phase
-
designing systems with maintenance in mind:
higher up-front cost may lead to lower total lifecycle
cost
-
this does not apply to disposable "walmartized"
systems
-
proof-of-concept systems
-
ship-it-now-or-lose-the-business systems
-
it just needs to be "good enough"
-
"technical debt"
-
maintaining software makes it worse over time:
progressive accumulation of workarounds, hacks, kludges
-
lecacy systems
-
by definition, successful sytems
-
represent
enormous
capital investment
-
hardest systems to maintain
-
accumulated maintenance
-
loss of tribal knowledge
-
we're not really smart enough to build complex systems
-
most projects fail, occasionally spectacularly;
traditional software engineering courses should cover case
studies because we keep making the same
mistakes
-
FAA Air Traffic Control modernization
-
healthcare.gov
-
successful systems generally start out as smaller systems
that
evolve
into larger ones
-
getting the
abstractions
right is key
-
abstraction
-
abstraction
-
API (Application Program Interface)
-
interface/implementaion
-
modeling
-
divide & conquer
-
modular decomposition
-
(object) encapsulation
-
public/private (class)
-
information hiding
-
leverage
-
libraries
-
abstraction!
-
assignment 1: build a web server
-
few dozen lines
-
if we had to do this from the socket system calls up,
it could be an entire term project
-
you ought to be
capable
of writing it from scratch if you had to, which
generally means having done it at least once
-
abstraction
-
did we mention abstraction?
-
refactoring
-
structural changes that do not affect behavior
-
no new features
-
no bug fixes
-
purpose: to make future maintenance easier
-
giving it a name makes the practice easier to sell to
management
-
many different kinds of software systems
System |
Ease/Cost of Update |
embedded
|
difficult/impossible
|
shrink-wrap
|
difficult
|
app store
|
phone home
|
cloud service
|
transparent
|
bespoke
|
???
|
-
don't apply disposable walmart techniques to life-critical systems
-
costly public breakdowns
-
Therac 25
-
Stuxnet (a Good thing)
-
Target/Home Depot
-
Sony
What is Software Engineering?
-
coined at 1968 NATO conference
-
"software crisis": hardware costs decreasing while software
cost increases
-
process models
-
goals:
-
build it predictably
-
build it better, faster, cheaper
-
quality is not a scalar quantity: many different aspects
-
performance
-
function
-
fit & finish
-
maintainability
-
etc.
-
tradeoffs
-
"sooner" may be better than "good"
-
"move fast & break things"
-
especially easy for cloud services where you can deploy
and roll back quickly
-
"good" may be better than "sooner"
-
especially for life-critical systems
What is Tactical (vs. Strategic)
-
focus on implementation
-
where the rubber meets the road
-
not the whole powertrain
-
important topics not covered:
-
case studies
-
process
-
requirements gathering
-
design documents
-
modeling/design tools (e.g. UML)
-
estimation
-
scheduling
-
project management
-
practices to support 10,000-line to 100,000-line systems
-
change management
-
build/test/deployment automation
-
bug tracking
-
code reviews
-
logs/logs analysis
-
debugging
-
refactoring
-
monitoring
-
load testing
-
load balancing
-
course expressly takes full advantage of the standard library
-
other courses are about
implementing
the abstractions
Goals & Non-Goals
Goals
-
implementation
-
build stuff & make it work
-
programming literacy
-
The Economist
vs.
USA Today
-
programming should not be the hard part of software
development
-
fluency comes with practice
-
develop appreciation for complexity & complexity management
-
how stuff is put together
-
did we mention the many facets of
abstraction?
-
course assignments will combine to form a scale model of a
distributed system
Non-Goals
Important points of implementation incidental to or outside the
scope of the course:
-
Go Language
-
learning Go is
incidental
-
if you do happen to learn Go, it will not be a Bad Thing for
your resume
-
concurrency
-
key design feature of Go, but not really the intended focus of
the course
-
note: while developing the material for the course, I realized
we really do need to talk about it
-
data structures & algorithms
-
important for understanding how stuff works
-
important for the job
interview:
see Joel Spolsky's comment on
pointers and recursion
-
important for understanding software performance characteristics
-
systems-level coding
-
you need to be able to interface with the operating system
-
web programming
-
no CSS/Javascript
-
incidental use of HTML
-
minimal use of HTTP as transport layer
-
project management
Why Go?
-
hot new language
-
I'm using it in my day job
-
different enough from C++ & Java to change the way you think
about programming
-
object model
-
concurrency (similar to Erlang)
-
cleaner, more concise syntax
-
has the feel of a scripting language
-
compiled
-
static type checking (seatbelts!)
-
explicit build step makes deployment not-completely trivial
-
convenient modern lanugage features
-
built-in lists/dictionaries (Golang terminology: slices/maps)
-
standardized look and feel:
go fmt
-
explicit emphasis on readability
-
consistency
-
clarity
-
transparency
-
explicit
-
don't be too clever
attitude
-
automatic documentatation from source:
go doc
-
designed for building software systems
-
kind of systems Google builds
-
good general-purpose language
-
not as exotic as Clojure/Scala/Erlang: more likely to see
widespread adoption
-
cheap, easy concurrency
Introduction to Go
-
compiled language
-
static typing: variables have a type, determined at compile time
-
tidier syntax, feels like a scripting language
-
fewer semicolons
-
required by the language spec, but the lexer (component of
the compiler) automatically inserts the semicolons into
the token stream at the
newlines
-
fewer parentheses
(
if
/for
)
-
fewer var declarations
-
:=
vs.
=
-
type inference: let the compiler do the work for you
-
no explicit global/export declarations: a file-scope name is
global if it begins with an uppercase letter, otherwise it is
private to the package
-
no
while
statement
-
multiple return values
-
second value often used for explicit out-of-band error
indication
-
explicit return makes it harder to ignore
-
predefined
error
type
-
every variable automagically initialized to its "zero" value
-
built-in string type
-
immutable: "alter" strings by creating new ones
-
C-style arrays: fixed size
-
not very important to the language: most of the time, use a
slice
-
slices: built-in list/vector type
-
maps: built-in dict/hash/associative array
-
struct type
-
structs are just data: no explicit declaration of methods
-
struct literals
-
interface type: function declarations
-
a type
implements
an interface if it implements all the functions of the
interface
-
no explicit declaration that a type implements an interface
-
no explicit class hierarchies: emphasis on composition, not
inheritance
-
pointers: present, but not as loud/obnoxious as C-style pointers
-
no pointer arithmetic
-
okay to return address of local variable
-
idomatic to take the address of a struct literal instead of
making explicit call to
new
-
defer
statement: ensure that a cleanup function will be called when the
current function returns
It's All About that Code
Simple
makefile
so you don't have to remember to reset your environment variables
(ymmv):
PACKAGES=...
TEST_PACKAGES=...
GOPATH=$(CURDIR)
GODOC_PORT=:6060
all: fmt install
install:
GOPATH=$(GOPATH) go install $(PACKAGES)
test:
#GOPATH=$(GOPATH) go test $(TEST_PACKAGES)
fmt:
GOPATH=$(GOPATH) go fmt $(PACKAGES)
doc:
GOPATH=$(GOPATH) godoc -v --http=$(GODOC_PORT) --index=true
clean:
Your basic hello world program (with a couple of in-class
additions): easily readable by anyone who never saw even a single
line of Go code.
// Hello is the standard hello world program.
// The documentation requires no special formatting or markups. Just
// write about the the thing you are documenting
//
// Odin and Zeus were here.
// Freyja and Hera were here.
package main
import (
"fmt"
)
// main does the deed.
func main() {
x := 2 * 4
fmt.Printf("Hello, world!, %d\n", x)
}
Note how the
godoc
command, with the right flags, fires off a web server with
documentation extracted from your source files seamlessly embedded
into the standard library documentation. Also note how no special
markup codes are required. Take some time to browse through the
standard library documentation.
Web Server
You can create a simple web server in a couple of lines using the
standard library.
Note that functions are first class objects: wherever you could use
the name of a function, you may use a function literal.
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func (response http.ResponseWriter, request *http.Request) {
fmt.Fprintln(response, "<html>\n<body>\n<h1>Hello, Apollo!</h1></body>")})
fmt.Printf("Server fail: %s\n", http.ListenAndServe(":8080", nil))
}
Of course, not the most easily-read piece of code, so let us break
it up a little, and avoid creating abusive function literals.
package main
import (
"fmt"
"net/http"
)
func hello (response http.ResponseWriter, request *http.Request) {
fmt.Fprintln(response, "<html>")
fmt.Fprintln(response, "<body>")
fmt.Fprintln(response, "<h1>Hello, Apollo!</h1>")
fmt.Fprintln(response, "</body>")
}
func main() {
http.HandleFunc("/", hello)
err := http.ListenAndServe(":8080", nil)
fmt.Printf("Server fail: %s\n", err)
}
Note that the code calls
fmt.Fprintln
on a
http.ResponseWriter
object.
Without getting into the details of Go's
interface
mechanism yet,
fmt.Fprintln
takes as the
file
parameter anything that
implements
the
io.writer
interface (from the
io
standard library package).
A common Go pattern is to have small single-function interfaces
named by appending "er" to the function name, so
a
Writer
is any object that implements a
Write
method.