Skip to content

Instantly share code, notes, and snippets.

@sranso
Last active March 29, 2021 16:51
Show Gist options
  • Save sranso/332e13dbbab802c16ec2 to your computer and use it in GitHub Desktop.
Save sranso/332e13dbbab802c16ec2 to your computer and use it in GitHub Desktop.

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 case HEAD) 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
  • 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
  • $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" vs grep $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

##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
  • 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 to ruby -v aka ruby verbose) on test_sepc.rb
  • and then <cr> is carriage 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. ultimately it will find TestDescribe which is wrong b/c in fact it is defined in the same class as describe. 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 converting block to a proc. now when you call the block, it will run as if it were a method on ExampleGroup meaning it now has access to that it method

##das-0004-source-code-history-integrity

  1. what history integrity means
  2. how to enforce it
  3. why do we care
  • mercurial hg vs git 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
  • more on git how it works etc

    • git add --all -- add all
    • git amend -- change latest commit message
    • git 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 branch master
        • docs on git-rev-list
          • Lists commit objects in reverse chronological order. so git rev-list --reverse will list them in chronological order
        • docs on git clean
          • removes untracked files from working tree
  • notes on using wc -l

    • stdin wc -l begin/index.html
    • stdout git lg | wc -l

das-0005-extracting-domain-objects

  • in vim, :map ,[key] [do something]
    • e.g. :map ,r :wqa
  • 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?

das-0007-growing-a-test-suite

  • 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

das-0008-processes-and-jobs

  • "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 on
    • fg 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.
      $ while true; do echo beep; sleep 1; done
      beep
      beep
      ctrl-z
      $ bg %1
      
      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.
  • just realized what suspended and interrupted mean when i do either ctrl-z or ctrl-c!
  • ps -- shows all processes
    • pstree -- like ps but shows who is the parent of processes
      • brew 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 hit screen -r
    $ pstree | view - # shows things in a vim file!
    
  • 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
    • you can diff a diff!
    diff -u <(git diff master~5..master~1) <(git diff master~4..master) | view -
    
    --> rarely useful (hah?) but can be good for comparing two branches...eh i mighta not understood that hah
    diff -u <(curl www.google.com | tidy) <(curl www.google.fr | tidy) | view -
    
    --> useful when comparing local server to production

das-0009-exceptions-and-control-flow

  • 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
@liamgriffiths
Copy link

🍏

@liamgriffiths
Copy link

i haven't done any ruby programming in well over a year, but reading this makes me want to a little bit

@sranso
Copy link
Author

sranso commented Jan 3, 2015

yeah, right?? i'm with you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment