2 - Idiomatic Code
2 - Idiomatic Code
Week 2
Idiomatic Code
1
Rising Competition
you competitor
Time
2
Rewrites are Common!
v2.0
Features
Lost time and
opportunities
(and new risks?)
v1.0
Joel Spolsky
Things You Should Never Do Give up and start
complete rewrite
you competitor
Time
https://www.wired.com/2013/06/facebook-hhvm-saga/
Pobar oversees a team of engineers charged with rebuilding the very foundation of the world's most
popular social network. They've toiled on this project for more than three years now…
3
Unix Shells
Command line interface for Unix operations
bash zsh zsh is a slightly more modern and easy to use shell
zsh is default in newer versions of MacOS
(bourne again shell) (Z shell)
.profile .profile setup commands for any shell or windowing system
.bashrc .zshrc commands & scripts to be run to configure any new shell
window that is opened
.bash_profile .zshenv commands & scripts to be run on user login into a shell
with username/password
4
Command Line Text Editors
Nano Emacs / Vi
Basic features
Best if you are new to Unix
http://www.tuxradar.com/content/text-editing-nano-made-easy http://www.tuxradar.com/content/emacs-tutorial-beginners
http://www.masteringemacs.org/articles/2010/11/01/running-shells-in-emacs-overview
Any unix process (e.g., git) that wants you to edit text or a file will now
automatically invoke your preferred text editor.
5
https://github.com/ISS-SOA/class-SOA-repo/wiki/resource-general#editors
GUI Text Editors
VisualStudio Code
code.visualstudio.com
Advantages
- Multiple cursors
- Extensive plugin options: git support, etc.
- Command Palette: ctrl-shift-p (Mac: cmd-shift-p)
6
rbenv
https://github.com/rbenv/rbenv
Use rbenv to manage your Ruby version Run a ruby app from the command line
$ rbenv $ ruby myapp.rb
# lists all rbenv commands
def website(names)
Method (function) to create search URL
search_terms = names.gsub(/[^a-zA-Z0-9]/, '+')
"https://www.google.com/search?q=#{search_terms}"
end
8
Code: https://github.com/ISS-SOA/demo_ruby_basics/blob/master/script.rb
Gems and Bundler
Gems 3rd party libraries for Ruby applications Hosted at: rubygems.org
Bundler
Gemfile.lock
$ gem install bundler Must install bundler gem once
GEM
remote: https://rubygems.org/
specs:
Gemfile
addressable (2.5.2)
source 'https://rubygems.org' public_suffix (>= 2.0.2, < 4.0)
...
$ bundle install http (2.2.2)
gem 'http'
List all gem dependencies in Gemfile addressable (~> 2.3)
http-cookie (~> 1.0)
http-form_data (~> 1.0.1)
http_parser.rb (~> 0.6.0)
http-cookie (1.0.3)
myapp.rb
domain_name (~> 0.5)
require 'http' ...
Use a gem in your code using require
PLATFORMS
# ... do something here ... Full list of all dependent gems and
ruby
their versions used for this project
DEPENDENCIES
$ bundle exec [...] Run a Ruby process using only gem versions in Gemfile.lock http
BUNDLED WITH
$ bundle exec ruby unidiomatic.rb https://soumyaray.com soumya.html 1.14.6 9
• allows you to write and evaluate code one line at a time
REPL • only available for dynamic languages (Python, Ruby, JS)
IRB Pry
(default interactive ruby shell) (alternative ruby shell that can be installed as a gem)
$ irb
$ gem install pry
> puts 'hello'
hello $ pry
=> nil [1] pry(main)> def greet(name)
[1] pry(main)* puts "Hello #{name}!"
> Time.now [1] pry(main)* end
=> 2014-09-21 16:33:45 +0800 => :greet
[2] pry(main)> greet('Soumya')
> def greet(name) Hello Soumya!
?> puts "Hello #{name}!" => nil
?> end
=> :greet
“Rubyists, It’s Time to PRY Yourself Off IRB!”
> greet('Soumya’) http://www.sitepoint.com/rubyists-time-pry-irb/
Hello Soumya!
=> nil
loop {
print("myrepl> ")
puts(eval(gets))
10
}
Ruby
“natural, not simple”
log_event(:search, [id_list, options]) Side Effects : external changes from running code
• Database writes
if options • File writes
# handle options • Network messages sent
end • Screen output, etc.
Idiomatic Ruby
Idiomatic: characteristic of a particular language or dialect
Returning from a one-line if is not preferred… Prefer using a guard clause for returns
if choice == 'exit'
return false return false if choice == 'exit'
else # Do your special thing here!
# Do your special thing here!
end
13
Closures: Blocks
A closure is a function that is "closed over" it’s free variables Blocks with arguments
source: http://www.skorks.com/2010/05/closures-a-simple-explanation-using-ruby/
status = 'Running the block…' func(2.0, 3.0) { |num1, num2| num1 / num2 }
=> "Result: 0.6666666666666666"
my_method { puts status; sleep(1) } Block of code sent to my_method
with all variables in current scope (status)
Starting my method Note: code should be shortened to idiomatic Ruby:
Running the block Note: error thrown if no block provided def func(x, y, &strategy)
Ending my method my_method result = block_given? ? yield(x, y) : x * y
=> nil # Starting my method "Result: #{result}"
# LocalJumpError: no block given (yield) end
14
read more: http://www.eriktrautman.com/posts/ruby-explained-blocks-procs-and-lambdas-aka-closures
Procedural loops: code for machines
15
http://stackoverflow.com/questions/28665528/while-do-while-for-loops-in-assembly-language-emu8086
Functional iteration with blocks
arr = [2,3,1,6,4,9]
2 3 1 6 4 9 2 3 1 6 4 9 3 1 9
Use for side effects
number 2
number 3
select
number 1
each number 6
number 4
number 9 Use for filtering
2 3 1 6 4 9 4 6 2 12 8 18 2 3 1 6 4 9 "2 - 3 - 1 - 6 - 4 - 9"
map reduce
17
Code: https://github.com/ISS-SOA/demo_ruby_basics/tree/master/iteration
No more for loops
code for humans: idiomatic functional map/reduce
sites = %w{slack facebook github codecademy canvaslms}
18
Code: https://github.com/ISS-SOA/demo_ruby_basics/tree/master/iteration
Style Guide: Wisdom of the Crowds*
Ruby Style Guide: https://github.com/rubocop-hq/ruby-style-guide
* developed by open source review by the Ruby community
html
end
How can we identify
site_url = ARV[0]
filename = ARV[1] violations in our code?
save_url(site_url, filename)
19
Code: https://github.com/ISS-SOA/demo_ruby_basics/tree/master/idiomatic
Static Code Analysis
also known as “Linting”
https://en.wikipedia.org/wiki/Lint_%28software%29
$ rubocop unidiomatic.rb
Inspecting 1 file
W
Extensions on your editor may allow rubocop to lint your code in real time
Extensions
21
Refactoring
(changing appearance of code without changing behavior)
Unidiomatic Idiomatic
require 'http' # frozen_string_literal: true
html
Is the idiomatic version clearer to read?
end Is the idiomatic version easier to change?
Features
Refactoring allows you to
easily add new features
you competitor
Time
23
Refactoring vs. Rewriting
Won't repeat bugs/mistakes from old code Take advantage of new tools and technologies
Won't lose time visibly innovating Take advantage of new talent in the market
Don't have to maintain old + new code New developers may appreciate a fresh start
Don't risk creating a worse outcome! Just cannot maintain old codebase any more
24
Assignment 2: Ruby Intermediate
25