Download Ruby for C# Developers

Document related concepts
no text concepts found
Transcript
Ruby for C# Developers
St. Louis
Code Camp
May 6th, 2006
Cory Foy
http://www.cornetdesign.com
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Overview
•
•
•
•
•
What is Ruby?
Ruby Basics
Advanced Ruby
Ruby and .NET integration
Wrap-up
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
What is Ruby?
• First released in 1995 by Yukihiro
Matsumoto (Matz)
• Object-Oriented
– number = 1.abs #instead of Math.abs(1)
• Dynamically Typed
– result = 1+3
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
What is Ruby?
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age.to_i
end
def inspect
"#@name (#@age)"
end
end
p1 = Person.new('elmo', 4)
puts p1.inspect
•
#
#
#
#
attributes we can set and retrieve
constructor method
store name and age for later retrieval
(store age as integer)
# This method retrieves saved values
# in a readable format
# elmo is the name, 4 is the age
# prints “elmo (4)”
http://www.rubygarden.org/faq/entry/show/3
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Will It Change Your Life?
•
•
•
•
Yes!
Ok, Maybe
It’s fun to program with
And what is programming if it isn’t fun?
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics
•
•
•
•
•
•
Variables, Classes and Methods
Properties / Attributes
Exceptions
Access Control
Importing Files and Libraries
Duck Typing
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Variables
• Local (lowercase, underscores)
– fred_j = Person.new(“Fred”)
• Instance (@ sign with lowercase)
– @name = name
• Class (@@ with lowercase)
– @@error_email = “[email protected]”
• Constant (Starts with uppercase)
– MY_PI = 3.14
– class Move
• Global ($ with name)
– $MEANING_OF_LIFE = 42
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Classes
class Move
attr_accessor :up, :right
def initialize(up, right)
@up = up
@right = right
end
end
• Class definitions are started with
class,are named with a CamelCase
name, and ended with end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Classes
class Move
attr_accessor :up, :right
def initialize(up, right)
@up = up
@right = right
end
end
• Attributes and fields normally go at the
beginning of the class definition
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Classes
class Move
attr_accessor :up, :right
def initialize(up, right)
@up = up
@right = right
end
end
• initialize is the same concept as a
constructor from .NET or Java, and is called
when someone invokes your object using
Move.new to set up the object’s state
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Methods
class Move
def up
@up
end
def right
return @right
end
end
• Methods return the last expression
evaluated. You can also explicitly return from
methods
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Methods
class Move
def initialize(up, right)
@up = up
@right = right
end
end
• Methods can take in specified
parameters, and also parameter lists
(using special notation)
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Methods
class Move
def self.create
return Move.new
end
def Move.logger
return @@logger
end
end
• Class (“Static”) methods start with
either self. or Class.
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Properties
• Like .NET, Ruby supports the concept
of Properties (called Attributes)
class Move
def up
@up
end
end
class Move
def up=(val)
@up = val
end
end
move = Move.new
move.up = 15
puts move.up #15
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Properties
• Unlike .NET, Ruby provides
convenience methods for doing this
class Move
attr_accessor :up
end
#Same thing as last slide
move = Move.new
move.up = 15
puts move.up #15
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Properties
• You can specify read or write only
attributes as well
class Move
attr_reader :up #Can’t write
attr_writer :down #Can’t read
end
move = Move.new
move.up = 15
d = move.down
St. Louis Code Camp
May 6th, 2006
#error
#error
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Exceptions
• Ruby has an Exception hierarchy
• Exceptions can be caught, raised and
handled
• You can also easily retry a block of
code when you encounter an exception
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Exceptions
process_file = File.open(“testfile.csv”)
begin
#put exceptional code in begin/end block
#...process file
rescue IOError => io_error
puts “IOException occurred. Retrying.”
retry #starts block over from begin
rescue => other_error
puts “Bad stuff happened: “ + other_error
else
#happens if no exceptions occur
puts “No errors in processing. Yippee!”
ensure
# similar to finally in .NET/Java
process_file.close unless process_file.nil?
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Access Control
• Ruby supports Public, Protected and
Private methods
• Private methods can only be accessed
from the instance of the object, not from
any other object, even those of the
same class as the instance
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Access Control
• Access is controlled by using keywords
class Move
private
def calculate_move
end
#Any subsequent methods will be private until..
public
def show_move
end
#Any subsequent methods will now be public
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Access Control
• Methods can also be passed as args
class Move
def calculate_move
end
def show_move
end
public :show_move
protected :calculate_move
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Imports
• To use a class from another file in your
class, you must tell your source file
where to find the class you want to use
require ‘calculator’
class Move
def calculate_move
return @up * Calculator::MIN_MOVE
end
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics - Imports
• There are two types of imports
– require
• Only loads the file once
– load
• Loads the file every time the method is executed
• Both accept relative and absolute paths, and
will search the current load path for the file
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
• What defines an object?
• How can you tell a car is a car?
– By model?
– By name?
• Or, by it’s behavior?
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
class CarWash
def accept_customer(car)
end
end
• How would we
validate this in
.NET or Java?
• We’d use static typing! So only the valid
object could be passed in
• What if my object has the same
behavior as a Car?
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
• What is
this?
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
• How
about
this?
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
• What
about
this?
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
• We know objects based on the
behaviors and attributes the object
possesses
• This means if the object passed in can
act like the object we want, that should
be good enough for us!
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Duck Typing
Class CarWash
def accept_customer(car)
if car.respond_to?(:drive_to)
@car = car
wash_car
else
reject_customer
end
end
end
• Or we could just let it fail as a runtime
error
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• In a static-typed language, how do we
use the compiler?
– Find misspellings
– Find improper usage
– Enforce contracts
– Find missing semicolons
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• What is a Unit Test?
• “In computer programming, a unit test is
a procedure used to validate that a
particular module of source code is
working properly.” (Wikipedia)
• Sounds like our compiler is just a unit
testing mechanism!
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• Ruby comes built in with a Unit Testing
framework – Test::Unit
– Create individual tests
– Create test suites
– Invoke our tests and suites
• Using this framework and Test-Driven
Development, we can have a high
confidence level in our code
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• Let’s build a toaster!
• Should be able to have
toasting levels set
• Should heat the bread based on
the toasting levels
• Different breads have different
cooking times.
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• Let’s start with a basic test
class TestToaster < Test::Unit::TestCase
def test_toast_bread
toaster = Toaster.new
bread = WonderBread.new
toaster.heat_level = 5
toaster.toast(bread)
assert_equal(“Nicely toasted”, bread.status)
end
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• And run it
root@dilbert $ruby testtoaster.rb
Loaded suite testtoaster
Started
E
Finished in 0.0 seconds.
1) Error:
test_toast_bread(TestToaster):
NameError: uninitialized constant TestToaster::Toaster
testtoaster.rb:4:in `test_toast_bread'
1 tests, 0 assertions, 0 failures, 1 errors
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• Next, let’s build our objects to allow our
test to run
class Toaster
attr_accessor :heat_level
def toast(bread)
class WonderBread
attr_accessor :status
end
end
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• And run them
root@dilbert $ruby testtoaster.rb
Loaded suite testtoaster
Started
F
Finished in 0.093 seconds.
1) Failure:
test_toast_bread(TestToaster) [testtoaster.rb:10]:
<"Nicely toasted"> expected but was
<nil>.
1 tests, 1 assertions, 1 failures, 0 errors
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• Finally, let’s make the test pass
class Toaster
def toast(bread)
bread.status = “Nicely toasted”
end
end
root@dilbert $ruby testtoaster.rb
Loaded suite testtoaster
Started
.
Finished in 0.0 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• We then keep writing tests to drive the
behavior of the code we want to write
• A side benefit is we get a suite of
regression tests for our code
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Unit Tests
• How did the compiler help us again?
– Find misspellings (Unit Tests)
– Find improper usage (Unit Tests)
– Enforce contracts (Duck Typing)
– Find missing semicolons (No semicolons!
;))
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Modules
•
•
•
•
•
Blocks and Iterators
Modules
Mixins / Inheritance
Reflection
Other Goodies
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Blocks
• A block is just a section of code
between a set of delimters – { } or
do..end
{ puts “Ho” }
3.times do
puts “Ho “
end
St. Louis Code Camp
May 6th, 2006
#prints “Ho Ho Ho”
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Blocks
• Blocks can be associated with method invocations.
The methods call the block using yield
def format_print
puts “Confidential. Do Not Disseminate.”
yield
puts “© SomeCorp, 2006”
end
format_print { puts “My name is Earl!” }
-> Confidential. Do Not Disseminate.
-> My name is Earl!
-> © SomeCorp, 2006
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Blocks
• Methods can act like the using statement from
.NET using blocks
def MyConnection.open(*args)
conn = Connection.open(*args)
if block_given?
yield conn #passes conn to the block
conn.close #closes conn when block finishes
end
return conn
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Iterators
• Iterators in Ruby are simply methods
that can invoke a block of code
• Iterators typically pass one or more
values to the block to be evaluated
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Iterators
def fib_up_to(max)
i1, i2 = 1, 1
while i1 <= max
yield i1
i1, i2 = i2, i1+i2 # parallel assignment
end
end
fib_up_to(100) {|f| print f + “ “}
-> 1 1 2 3 5 8 13 21 34 55 89
•
Pickaxe Book, page 50
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Modules
• At their core, Modules are like
namespaces in .NET or Java.
module Kite
def Kite.fly
end
end
module Plane
def Plane.fly
end
end
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Mixins
• Modules can’t have instances – they
aren’t classes
• But Modules can be included in
classes, who inherit all of the instance
method definitions from the module
• This is called a mixin and is how Ruby
does “Multiple Inheritance”
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Mixins
module Print
def print
puts “Company Confidential”
yield
end
end
class Document
include Print
#...
end
doc = Document.new
doc.print { “Fourth Quarter looks great!” }
-> Company Confidential
-> Fourth Quarter looks great!
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Reflection
• How could we call the Length of a
String at runtime in .NET?
String myString = "test";
int len = (int)myString
.GetType()
.InvokeMember("Length",
System.Reflection.BindingFlags.GetProperty,
null, myString, null);
Console.WriteLine("Length: " + len.ToString());
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Reflection
• In Ruby, we can just send the
command to the object
myString = “Test”
puts myString.send(:length)
St. Louis Code Camp
May 6th, 2006
# 4
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Advanced Ruby - Reflection
• We can also do all kinds of fancy stuff
#print out all of the objects in our system
ObjectSpace.each_object(Class) {|c| puts c}
#Get all the methods on an object
“Some String”.methods
#see if an object responds to a certain method
obj.respond_to?(:length)
#see if an object is a type
obj.kind_of?(Numeric)
obj.instance_of?(FixNum)
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Basics – Other Goodies
• RubyGems – Package Management for
Ruby Libraries
• Rake – A Pure Ruby build tool (can use
XML as well for the build files)
• RDoc – Automatically extracts
documentation from your code and
comments
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby and .NET
• Why?
– Provide Scripting ability in your apps
– Quickly prototype
– Class Introspection
• What about JScript.NET?
– Ruby is cross platform
– JScript might be better choice
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby and .NET
• Three projects in the works
• Ruby to .NET Bridge
– http://rubydotnet.sourceforge.net/
• MS Funded Ruby CLR project
– http://www.plas.fit.qut.edu.au/rubynet/
• RubyCLR
– http://rubyforge.org/projects/rubyclr
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby and .NET
• Bridge Example
– Basic Arrays
– Interacting with Objects
– Creating Forms
– Attaching to Events
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com
Ruby Resources
• Programming Ruby by Dave Thomas (the
Pickaxe Book)
• http://www.ruby-lang.org
• http://www.rubyforge.org
• http://www.rubycentral.org
• http://www.ruby-doc.org
• http://www.rubygarden.org
• http://www.stlruby.org
St. Louis Code Camp
May 6th, 2006
Ruby for C# Developers
Cory Foy
http://www.cornetdesign.com