Skip to content

Commit fd7fe92

Browse files
committed
Add c4s1
1 parent 820213b commit fd7fe92

7 files changed

+194
-46
lines changed
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
title: Improving code
3+
---
4+
5+
This session we're going to be looking at ways to improve the code you write. In particular, we're going to see how to use *functions* to begin to separate out program logic into reusable chunks.
6+
7+
### Why do we need functions?
8+
9+
Take a look at this bit of code taken from a sinatra app:
10+
11+
{% highlight ruby %}
12+
@swimmer_first_name = @swimmer[:name].split.first
13+
@swimmer_last_name = @swimmer[:name].split.last
14+
@swimmer_dob = @swimmer[:dob]
15+
16+
@cyclist_first_name = @cyclist[:name].split.first
17+
@cyclist_last_name = @cyclist[:name].split.last
18+
@cyclist_dob = @cyclist[:dob]
19+
20+
@runner_first_name = @runner[:name].split.first
21+
@runner_last_name = @runner[:name].split.last
22+
@runner_dob = @runner[:dob]
23+
{% endhighlight %}
24+
25+
This code contains a lot of repetition. Some of the repetition might be unavoidable: we might really need to set up all those different instance variables to share with a view. Other bits aren't and will cause us problems in the long run.
26+
27+
The duplication of the logic for extracting the first and last name is particularly problematic:
28+
29+
* If we wanted to change the way a last name was extracted from a name (e.g to take into account names like 'Pierre de Fermat') we'd have to make changes in three places.
30+
* The code is also cluttered and harder to make sense of than it needs to be: each time you read `.split.first` your brain has to convert that into 'find the first name'. As a programmer you will spend more time reading code than writing it, so these considerations are important.
31+
32+
A nicer way to write this code would be to use `first_name` and `last_name` functions, that contain the logic for splitting up the name:
33+
34+
{% highlight ruby %}
35+
@swimmer_first_name = first_name(@swimmer[:name])
36+
@swimmer_last_name = last_name(@swimmer[:name])
37+
@swimmer_dob = @swimmer[:dob]
38+
39+
@cyclist_first_name = first_name(@cyclist[:name])
40+
@cyclist_last_name = last_name(@cyclist[:name])
41+
@cyclist_dob = @cyclist[:dob]
42+
43+
@runner_first_name = first_name(@runner[:name])
44+
@runner_last_name = last_name(@runner[:name])
45+
@runner_dob = @runner[:dob]
46+
{% endhighlight %}
47+
48+
{% exercise %}
49+
1. Clone down the sinatra app for this session: [https://github.com/code61/sinatra_c4s1](https://github.com/code61/sinatra_c4s1).
50+
2. Install the required libraries: `cd sinatra_c4s1` and then `bundle install`.
51+
2. Familiarise yourself with the app, by looking through the code and running the app from the command line (`ruby app.rb`).
52+
3. See if you can identify other places where logic could be cleaned up.
53+
{% endexercise %}

_sessions/c4s1/2_functions.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: Functions
3+
---
4+
5+
A *function* (or *method*) is a way of separating out a piece of programming logic so that you can use it elsewhere.
6+
7+
### Defining and calling a function
8+
9+
There are two steps in using a function
10+
11+
1. *Define* the function: to define a function you need to give it a name and write the code contained in the function.
12+
2. *Call* the function: when you use the function, we say that the function is being 'called'. Calling a function causes the code inside it to be run.
13+
14+
{% highlight ruby %}
15+
def first_name(full_name)
16+
full_name.split.first
17+
end
18+
19+
first_name('Tom Close') #=> 'Tom'
20+
first_name('Ashok Menon') #=> 'Ashok'
21+
{% endhighlight %}
22+
23+
In the example above the function takes a single *parameter* (in this case the full name that you want to split up).
24+
25+
* When you call the function you give it the full name (e.g. `"Tom Close"`) as a string.
26+
* The the variable `full_name`, that you specified in the function definition, is set to the name you provided. In this case this is equivalent to `full_name = "Tom Close"`.
27+
* The statements inside the function body are then executed.
28+
* The function *returns* the value of the last expression to be evaluated.
29+
30+
{% exercise %}
31+
1. **Fork** and clone down the exercises for this session: [https://github.com/code61/exercises_c4s1](https://github.com/code61/exercises_c4s1)
32+
2. Install the gems you need - in the `exercises_c4s1` folder, run: `bundle install`
33+
3. Open `names.rb` in sublime text.
34+
4. Using the code above fill out the `first_name` function.
35+
5. Open `irb` and load in the file by running `load 'names.rb'`.
36+
6. Try the function out, by calling it in irb.
37+
7. Close `irb` and run the tests we've provided for the function by running `rspec spec/first_name_spec.rb`.
38+
8. Now try and write the body of the `last_name` function. Follow the same procedure of trying in irb, then running the test `rspec spec/last_name_spec.rb`.
39+
9. (Ext) Improve your `last_name` function, so that it can cope with composite last names (treating everything after the first name as the last name). Test your solution by running `rspec spec/ext_last_name_spec.rb`
40+
10. (Ext) Work through the functions in `date.rb`. Test your solutions running the tests in files `spec/month_spec.rb`, `spec/last_digit_spec.rb`, `spec/penultimate_digit_spec.rb`, `spec/ordinal_suffix_spec.rb` and `spec/date_in_words_spec.rb`.
41+
{% endexercise %}
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: More about arguments
3+
---
4+
5+
So far we've only looked at functions with a single argument. What if we want to have no parameters, multiple parameters or a variable number?
6+
7+
### Functions with no parameters
8+
9+
It is sometimes useful to have a function with no parameters, often for a task that you need to perform repetitively:
10+
11+
{% highlight ruby %}
12+
require 'csv'
13+
14+
def load_data
15+
# read data in from the csv file
16+
data = CSV.read('tmp/students/data.csv')
17+
18+
# remove the header row
19+
data[1..-1]
20+
end
21+
{% endhighlight %}
22+
23+
When you call a function with no parameters, you don't need to use brackets:
24+
25+
{% highlight ruby %}
26+
27+
load_data #=> [[..], [..], [..], ...]
28+
29+
{% endhighlight %}
30+
31+
<p class='small'>[In fact you don't need brackets when you're calling a function with arguments either. For the time being we'll use them though, to keep things simple.]</p>
32+
33+
### Functions with multiple parameters
34+
35+
Defining and calling a function with multiple parameters is just like defining and calling one with a single parameter:
36+
37+
{% highlight ruby %}
38+
def insult(word, strength)
39+
"#{word.capitalize} off" + '!' * strength
40+
end
41+
42+
insult('goose', 4) #=> "Goose off!!!!"
43+
{% endhighlight %}
44+
45+
When you call a function with multiple parameters, you need to make sure you provide the right number, otherwise you'll get an error.
46+
47+
{% highlight ruby %}
48+
insult('badger', 4, 5)
49+
#=> ArgumentError: wrong number of arguments (3 for 2)
50+
#=> from (pry):2:in `insult'
51+
{% endhighlight %}
52+
53+
### Functions with optional parameters
54+
55+
Sometimes it's useful to be able to supply a parameter if you want, but use a sensible default otherwise:
56+
57+
{% highlight ruby %}
58+
def i_love(thing = 'ruby')
59+
"I love #{thing}!"
60+
end
61+
62+
i_love('coding') #=> "I love coding!"
63+
i_love #=> "I love ruby!"
64+
{% endhighlight %}
65+
66+
{% exercise %}
67+
1. Open `more_functions.rb` and begin to work your way throught the functions in the file.
68+
2. For each function you write, reload the file into irb to try it out: `load 'more_functions.rb'` (run this **inside** `irb`).
69+
3. For each function you write, run the appropriate test e.g.: `rspec spec/multiply_and_sum_spec.rb` (run this **outside** `irb`, on the command line).
70+
4. If you get onto the `describe_result` function, you will need to start by writing your own test in `spec/describe_result_spec.rb`. (Do this by copying and pasting from another test, and make the appropriate changes.)
71+
{% endexercise %}
72+
{% endexercise %}

_sessions/c4s1/4_refactor_example.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
title: Refactoring
3+
---
4+
5+
**Refactoring** is the act of restructuring a piece of code **without changing its behaviour**. Refactoring is very important in software development, as without it software projects quickly become unweildy and difficulat to work with.
6+
7+
You're going to refactor the sinatra app, by completing the functions in the `helper_functions.rb` file.
8+
9+
{% exercise %}
10+
1. Open `app.rb` in Sublime Text.
11+
2. Uncomment the commented out `post` block at the bottom, and comment out the other one. This is how we want the code to look, but currently the functions aren't there to make this work.
12+
3. Uncomment the line `require './helper_functions'` at the top of `app.rb`
13+
3. Open the file `helper_functions.rb` in Sublime Text. Complete the functions so that the app works as before.
14+
{% endexercise %}

_sessions/c4s1/5_homework.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Homework
3+
---
4+
5+
{% exercise %}
6+
1. Finish off any exercises from class.
7+
2. Do the [Codecademy Ruby track](http://www.codecademy.com/tracks/ruby) Sections 9 and 10.
8+
{% endexercise %}

course3.md

-42
Original file line numberDiff line numberDiff line change
@@ -39,45 +39,3 @@ layout: default
3939
- [Session 4](c3s4)
4040
+ sending emails?
4141
+ Hashes
42-
43-
44-
- [Session 1](c4s1)
45-
+ functions
46-
+ lots of exercises with tests
47-
+ [hwk] refactor a sinatra app
48-
- [Session 2](c4s2)
49-
+ more functions
50-
- [Session 3](c4s3)
51-
+ mongodb/classes
52-
- [Session 4](c4s4)
53-
+ CRUD app
54-
55-
56-
name can be a variable, a Constant, (an @instance variable, a @@class variable, $global)
57-
http://rubylearning.com/satishtalim/ruby_names.html
58-
59-
adding numbers
60-
string interpolation
61-
62-
(methods puts)
63-
64-
sinatra: returns last expression in the block to the web browser, url matching, getting param from url, string interpolation
65-
deploying?
66-
67-
SESSION2
68-
69-
conditionals
70-
sinatra templates? (only showing values)
71-
form submissions? (with validations?) - example of a function??
72-
FOAAS ?? / text-based game
73-
74-
SESSION3
75-
76-
collections & iterating
77-
providing the contents of a file?
78-
similar to sinatra3?
79-
80-
SESSION4
81-
82-
hashes - explaining params,
83-
building an api?

course4.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ layout: default
1111
- [Preparation](c4prep)
1212

1313
- [Session 1](c4s1)
14-
14+
+ functions: defining, calling
15+
+ lots of exercises with tests
16+
+ [hwk] refactor a sinatra app
1517
- [Session 2](c4s2)
16-
18+
+ more functions
1719
- [Session 3](c4s3)
18-
20+
+ mongodb/classes
1921
- [Session 4](c4s4)
20-
22+
+ CRUD app

0 commit comments

Comments
 (0)