james crisp and jim webber, thoughtworks arc310. platform code affordances tool support...
Post on 22-Dec-2015
220 views
TRANSCRIPT
Learning to Live with the Static Typing Fascist and the Dynamic Typing Fanboy in your Enterprise...
James Crisp and Jim Webber, ThoughtWorks
ARC310
Roadmap
PlatformCode affordancesTool supportExtensibilityDevelopment ProcessData accessMetaprogrammingApplication developmentIntegration
Platform
Windows!.Net 3.5
Maybe Linux, via Mono
Platform
AnywhereWindowsLinuxMacCLRJVM
Readability
How concise and readable is thecode?How much code will I have to maintain?How productive can I be?
Attributes
class Person attr :id attr_accessor :name, :ageend
Named Parameters
p = Person.new(:first_name => "Freddy",:last_name => "Flintoff")
p.update(:age => 72, :sex=>'m')
Default PropertyImplementationclass Person{ public string FirstName { get; set; }...
Initialisers
Person p = new Person { LastName = "Dundee", FirstName = "Mick" };
Meta Plumbing
class DomainObject def initialize(attributes = {}) attributes.each do |name, value| eval("@#{name} = value") end end end
Duck Typing
h = House.new( number => 20 )p = Phone.new( number => 123456 )
p = h
p.number >> 20
Type Inference
var p = new Person { LastName = "Smith"};
Who needs Duck Typing?
interface INumbered{ int Number { get; }}
class House : INumbered ...class Phone : INumbered ...
INumbered phone;INumbered house = new House();phone = house;phone.Number
Data
LINQ and Entity FrameworkCastle project
Active record for .NetBuilds on NHibernate
NHibernate too!
Design Time
Generate and Use theDatabasePersonDataContext pdc = new PersonDataContext();pdc.CreateDatabase();
var adults = from p in pdc.Persons where p.Age > 18 select p;
foreach (Person adult in adults){ Console.WriteLine(adult.FirstName + " " + adult.LastName);}
Data
Active Record ships with RailsGood for green field web appsObjects and properties mapped 1:1 to tables and columnsSimple API for searching and saving
Can use underlying platform – eg, Hibernate or NHibernate
Lambda Functions
What are Lambda functions?
From the functional programming community
Who?
Think: anonymous inline methodsC# 2.0 anonymous delegates with nicer syntax
Pass a function into acollectionList<Person> people = new List<Person>();people.Add(new Person { FirstName = "James", LastName = "Crisp", Age = 8 });
people.Add(new Person { FirstName = "Jim", LastName = "Webber", Age = 32 });
people.ForEach(p => Console.WriteLine(p.FirstName + " " + p.LastName));
Lambda Functions
codgers = people.find {|p| p.age > 30}
codgers.each {|c| print c.name }
Metaprogramming & DSLs
Method Missing
DSLs
Code generation at run time
Method Missing
If a method is not defined, falls through to ‘method_missing’.
ActiveRecord (part of Rails) uses this to “generate” properties on domain objects at run time.
Allows DSLs like :Person.find_by_name_and_age('Jim', 84)
Code Generation atRun Time
Create new properties, methods and classes on the fly
Redefine, wrap and rename methods
Eval() a string, and it will be code
Code Generating DSL
class Geek < ActiveRecord::Basehas_many :laptopshas_one :girlfriend
end
jim = Geek.new(:name => 'Jim' )laptop = Laptop.new(:brand=> 'dell')jim.laptops << laptop
rSpec DSL
describe Geek do before(:each) do @geek = Geek.new end
it "should have no laptops initially" do @geek.laptops.count.should == 0 end
....
Autogen andMetaprogramming
Can generate useful code from metadata at compile time
E.g. Domain objects from database schemasE.g. Service proxies from WSDLEtc
Attributes for metaprogrammingAnd the reflection APIs if I have to...
DSLs
Some support for fluent interfacesin NUnit etc
Assert.That(...);Assert.IsNotNull(...);
Can create our own DSLs by using cunning class name conventions
E.g. nBehave for BDDLike TDD but focussed on behaviour rather than implementation
nBehave DSL
override public void Specify(){ Given(new RubyProgrammer()). When(new BuildingProperSoftware()). Then(new RubyProgrammerShouldBeFired());} Tooling available to turn
this code into development stories for
xBehave
Extensible Type System
All classes are open and can beextendedEg, Rails extends Ruby's number class: >> 5.days.from_now => Sun Aug 05 14:28:12 +1000 2007
Existing methods can be removed, wrapped or renamed
Frameworks often designed around re-usable Mixins rather than inheritance
Adding new methods
class String def url? self.starts_with? "http://" endend
>> "hi".url?=> false>> "http://jamescrisp.org".url?=> true
Extensible Type System
We’ve always had interfaces andabstract classes from the underlying .Net frameworkNow we have extension methods too...
Defining Extension Methods
namespace JimWebber{ public static class WebUriValidator { public static bool IsValidUri(this string str) { return str.ToLower().StartsWith("http"); } }}
Using Extension Methods
using JimWebber;class Program{ static void Main(string[] args) { string s ="http://jim.webber.name"; bool b = s.IsValidUri(); }}
Testing
Unit Testing TDD – NUnit BDD – nBehavenMock – Interfaces easy, classes slightly trickier
NUnit
[TestFixture]public class PersonTest{ [SetUp] public void GivenAPersonExists() {..} [TearDown] public void PersonShouldBeRemoved() {..} [Test] public void PersonShouldBeOlderThanZero() { ... Assert.That(p.Age > 0); }}
nMock Example
InterfaceToBeMocked aMock = mocks.NewMock<IPerson>();
Stub.On(aMock).GetProperty("Age") .Will(Return.Value(32));
Expect.Once.On(aMock) .GetProperty("FirstName") .Will(Return.Value("Jim"));
Testing
TDDUnit test framework part of standardlibraries
BDDrSpec, rBehave
MocksMocha, rMock, FlexMock, etc
Unit Test Example
def test_person_is_called_james do assert_equal 'James', @person.nameend
OR after a little bit of meta programming
test 'person is called James' do assert_equal 'James', @person.nameend
Mocha Example
p = mock('person')
p.stubs(:age).returns(26)
p.expects(:name).returns('James')
Tool Support
Visual StudioIntellisense, debugger, PowerShell, etc
Continuous IntegrationCruiseControl.Net and friends
Build ProcessNAnt, MSBuild, NMaven, etc
PowerShell
PS C:\Users\Jim Webber> $name = "Jim Webber"PS C:\Users\Jim Webber> $nameJim WebberPS C:\Users\Jim Webber> $name.ToLower()jim webberPS C:\Users\Jim Webber>
PS C:\Users\Jim Webber> ([xml](new-object System.Net.WebClient).DownloadString("http://jim.webber.name/feeds/atom.aspx") ).feed.titleWorld Wide Webber
Tool Support
IDE Visual Studio with Iron RubyIntelliJ, e-Edit, TextMate provide syntax highlighting and script support.
Build Process: Rake
Continuous IntegrationCruiseControl.rb and friends
Console
C:\ruby>ruby script/console>> p = Person.new( :name => 'Jim' )=> #<Person:0x49c8d40 @attributes={"name"=>"Jim"}, ...>>> p.save>> name = 'Jim'>> Person.find(:first, ['name = ', name])=> #<Person:0x69c1d40 @attributes={"name"=>"Jim"}, ...>
Gems
C:\ruby> gem install mocha
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed mocha-0.5.3
Installing ri documentation for mocha-0.5.3...Installing RDoc documentation for mocha-0.5.3...
NMaven
Apache Incubator projectSupports repositories for dependencies
Across the InternetPlugs into the standard Maven build cycleWill have VS integrationExtensible through Mono-based plugins
Also could use Ivy for dependency management...
Warning: NMaven currently immature
Web Apps RAILSRails is the most famous and popularRuby framework
Rails provides (among other things):Neat MVC framework and route mappingTemplate based viewsDomain focussed business layerActive Record and DSLs for persistenceEasy AJAX and Web 2.0 supportAuto-generated code (write time and run time)Fast change cycle (edit file -> refresh page)Plug-ins for code re-use
Web Apps
ASP.NetPlus new ASP.Net AJAX functionality
Combine ASP.Net with Entity Framework for Rails-like functionality
SilverlightFor richer client functionality
Rich Client
Most Ruby dev is Rails and Web 2.0
There are GTK / Gnome bindings for Ruby and some rich client Ruby apps.
WPF under .NET
Rich Client
WPFClear separation of markup andbusiness logicWhizzy acceleration and goodness from DirectX 10
Also the older WinForms stuff is available
Integration
WCF WS-*
SOAP, WSDL, WS-Sec, WS-SecPol, WS-Trust, WS-Federation, WS-Coordination. WS-AtomicTransaction, WS-KitchenSink...
REST SupportURI templates, [WebGet], etc
Enterprise-y stuff tooQueues
Integration
REST-centricWeb services are produced like web pages, using same framework and routingMessage Queues using Reliable-Msg or underlying JMS or MSMQWS-* support
SOAP4RUse underlying platform for WS-*, eg, WCF or Java frameworks like XFire
XML and Friends
.Net has XmlSerializer (and friends)Dom, XPath, templates, etc
VB has XML literal support...Dim x As XElement = <date> <year>2006</year> <month>01</month> <day>01</day> </date>
C# Not Tightly Coupled toXMLvar x = new XElement("Date");x.Add(new XElement("Year", "2006"));x.Add(new XElement("Month", "01"));x.Add(new XElement("Day", "01"));
XML and Friends
XPath and Document Object Modelwell supported
To generate complex XML (eg, LIXI), the best way is templating using Erb
All objects have to_xml method with serialises properties to xml
XML Builder is nice to work with and leverages Ruby's flexible method_missing
XML Builder
>> builder.date { ?> builder.year "2006" >> builder.month "01" >> builder.day "01" >> } <date> <year>2006</year> <month>01</month> <day>01</day><date>
Coexisting in theenterprise
When to go Ruby versuswhen to use C# and .Net?
Enterprise “heavy lifting?”
Cross-language enterprise development?
And what about mixing C# and IronRuby...?
Questions?Ask James and Jim!
ARC 310
Evaluation FormsDon’t Forget!
ARC 310