notes of things i learn while watching destroy all software
##das-0001-statistics-over-git-repositories
git rev-list HEAD
-- takes the ref (in this caseHEAD
) and crawling backwards. so the most recent commit will appear first- to reverse (have most recent be first)
git rev-list --reverse HEAD
oldest -> newest
- to reverse (have most recent be first)
xargs
- takes multiline output and joins them with a space
- e.g.
$ echo '1 > 2 > 3' | xargs 1 2 3 $ echo '1 > 2 > 3' | xargs ls ls: 1: No such file or directory ls: 2: No such file or directory ls: 3: No such file or directory
- useful when you have something coming out of stdout and want to pass it something else as arguments
- control scripts like
while
loop has stdin and stdout wc -l
word count, lines --> counts number of lines, stdin- to make a script
- create file, e.g.
stats.sh
- put shebang at top e.g.
#!/bin/bash
- add
set -e
-- if any command in script fails, the whole thing will abort. default is to continue. - write the command below e.g.
git rev-list --reverse HEAD | while read rev; do echo echo REV $rev; git ls-tree -r $rev | awk '{print $3}' | xargs git show | wc -l done
- run file
$ ./stats.sh
- create file, e.g.
$1 $2 $3..
1st 2nd 3rd arguments in a script- good practice: quote your variables as you're passing them as arguments, e.g.
grep "$file_pattern"
vsgrep $file_pattern
- assuming the var
$file_pattern
is empty, this is what grep would be doing: - w/o
""
: grep required a pattern so this will throw an error - w
""
: grep will interpret the pattern as an empty string, sit on stdin. shell will see that there's an arg, and pass that""
to grep, which is different than passing nothing to grep
- assuming the var
##das-0002-how-and-why-to-avoid-nil
- why to avoid nil
- can throw untraceable errors because the "source" could be deep in the stack trace. ideally the line that introduced the
nil
will be in the stack trace
- can throw untraceable errors because the "source" could be deep in the stack trace. ideally the line that introduced the
- how
- use lang/library in order to prevent nils in first place
- invert the obj relationship
- guard against nils in a manual attribute reader
- introduce new domain concepts
- good practice: in rails if there's a bang method, almost always want to use it (bc will throw exceptions, not nils)
i'm excited to understand what this is doing:
:map ,t :w\|:!ruby test_spec.rb<cr>
map
the keystrokes,t
with the following commands::w
save the file- then pipe
|
(escaping it) the stdout to the command line - and
!ruby
(which is evaluated toruby -v
aka ruby verbose) ontest_sepc.rb
- and then
<cr>
iscarriage return
and for more on vim keys, you can run:help key-notation
:mic-drop:
##das-0003-building-rspec-from-scratch
- kernel
- never toootally understood this, but by context he made it seem like kernel == the global namespace
- ruby docs make it seem like kernel refers to things that are avail. to every ruby obj. so sorta like ^^
- similar to js, ruby will look up the environment chain for what it's looking for. e.g.
#test_spec.rb class TestDescribe < Test::Unit::TestCase def test_that_it_can_pass describe 'some thing' do it 'has some property' do end end end end
- (remember we're rewriting)
- here
describe
has been defined in a class but is not itself a class.it
will move up the environmental chain looking for a class from where it assumes it was defined. ultimatelyit
will findTestDescribe
which is wrong b/c in factit
is defined in the same class asdescribe
. here's what you do to clarify:
#spec.rb def describe(description, &block) ExampleGroup.new(block).evaluate! end class ExampleGroup def initialize(block) @block = block end def evaluate! instance_eval(&@block) #previously was @block.call end def it(description, &block) block.call end end
instance_eval
exists to solve this purpose. put&
in front of it bc we're convertingblock
to aproc
. now when you call the block, it will run as if it were a method onExampleGroup
meaning it now has access to thatit
method
##das-0004-source-code-history-integrity
- what history integrity means
- how to enforce it
- why do we care
-
mercurial
hg
vsgit
world- mercurial is distributed revision control, mainly for python. binary diff implementation written in c
- immutable history, don't change commits after they're made
- git
- there's support for editing/removing/reordering history to make the commits read nicely
- mercurial is distributed revision control, mainly for python. binary diff implementation written in c
-
more on
git
how it works etcgit add --all
-- add allgit amend
-- change latest commit messagegit rebase -i master~2
-- rebase and update refs/heads/master two commits back.- docs on git-rebase
-i
==--interactive
aka "Make a list of the commits which are about to be rebased. Let the user edit that list before rebasing. This mode can also be used to split commits."- 3 danger of doing this: can break introducing commits into history that have never had tests run against them.
git rev-list --reverse master | while read rev; do git co $rev && git clean -fd && python runtests.py; done; git co master
- this will
co
to each commit, remove untracked files, and run tests on every revision in history on branchmaster
- docs on git-rev-list
- Lists commit objects in reverse chronological order. so
git rev-list --reverse
will list them in chronological order
- Lists commit objects in reverse chronological order. so
- docs on git clean
- removes untracked files from working tree
- this will
-
notes on using
wc -l
- stdin
wc -l begin/index.html
- stdout
git lg | wc -l
- stdin
- in vim,
:map ,[key] [do something]
- e.g.
:map ,r :wqa
- e.g.
- multiple expectations in spec is generally a bad idea -- have one expectation with multiple k-v pairs
- structs can give helpful context
- e.g.
Month = Struct.new(:year, :month) # [2010, 01] vs <struct Month year=2010, month=2>
- inline variables that are only used once
- if old specs aren't useful anymore, remove them and rewrite them to adapt to new functionality
- what does it mean to invoke the controller in a spec?
- ruby instance variables are
nil
by default as_null_object
tells a stub to ignore all unknown method calls- e.g.
cheese = stub(:edible? => true, :energy => 100).as_null_object # now cheese will ignore gift.digest! later (where gift is cheese)
- don't want to see a test pass on it's first go -- want it to fail first so you can validate it passes for the right reasons, and that it is actually testing something
- it's not always clear to me when to abstract a class/var
- "few things are more unix-y than process management and job control"
- in unix, everything is a file (that's their philosophy)
jobs
-- shows all jobs going onfg
brings up the last job%[num]
brings up that specific job -- e.g.%1
- in bash you can say
fg 1
but in zsh you can't bg %[num]
-- will run a job in the background- e.g.
will continue to run but not in the foreground (though it didn't work for me just now? was in foreground). can bring it to fg.$ while true; do echo beep; sleep 1; done beep beep ctrl-z $ bg %1
- just realized what
suspended
andinterrupted
mean when i do either ctrl-z or ctrl-c! ps
-- shows all processespstree
-- like ps but shows who is the parent of processesbrew install pstree
(if you're on linux you prob have it already)
screen
--- can run a rails server
rails -s
, hit ctrl a-d to detach -- wont be in jobs list or foreground. to bring it back you can hitscreen -r
$ pstree | view - # shows things in a vim file!
- can run a rails server
- he encourages "single terminal development" -- do everything you need to do in one terminal
- for him, he seems to run the server, detach from it, open vim and work with source code, and every now and then put it in the background so he can interact w/ git or w/e
diff
- you can
diff
two totally unrelated files! e.g.diff hi.md bye.md
diff -u ...
makes it pretty..?diff <() <()
- everything in
<()
is a subshell, and you can put anything in it
-->➜ tmp git:(master) ✗ diff -u <(echo hi) <(echo bye) --- /dev/fd/11 2015-06-01 19:58:42.000000000 -0400 +++ /dev/fd/12 2015-06-01 19:58:42.000000000 -0400 @@ -1 +1 @@ -hi +bye
/dev/fd/11
are paths on the disk that represent file descriptors, and those file descriptors are not files on the disk but they are pipes; you can pass them around as arugments- everything in
- you can diff a diff!
--> rarely useful (hah?) but can be good for comparing two branches...eh i mighta not understood that hahdiff -u <(git diff master~5..master~1) <(git diff master~4..master) | view -
--> useful when comparing local server to productiondiff -u <(curl www.google.com | tidy) <(curl www.google.fr | tidy) | view -
- you can
- when developing, he often asks questions aloud, some examples
- what are we coupling ourselves to?
- do i like how this reads
- is this code still useful
- he doesn't like the special cases surrounding the general cases
if special case general thing else special thing # so instead you can do try: general thing except KeyError: special thing
- don't use exceptions for control flow too strictly
🍏