samedi 26 mai 2012

Introduction to Ruby and Rails

Ruby is an Interpreted and Object-oriented language where Everything is an object and Every operation is a method call on some object.
Ruby is Dynamically typed, i.e. objects have types, but variables don’t. Dynamic means add, modify code at runtime (metaprogramming), ask objects about themselves (reflection), and in a sense all programming is metaprogramming.


Ruby is ...


an Interpreted and Object-oriented language where Everything is an object and Every operation is a method call on some object.
Ruby is Dynamically typed, i.e. objects have types, but variables don’t. Dynamic means add, modify code at runtime (metaprogramming), ask objects about themselves (reflection), and in a sense all programming is metaprogramming.


Naming conventions

Class names use UpperCamelCase, for instance class FriendFinder ...  end
Methods and variables use snake_case, for def learn_conventions  ...  enddef faculty_member?  ...  enddef charge_credit_card!  ...  end.
Constants (scoped) & $GLOBALS (not scoped) are must be in upper case: TEST_MODE = true, $TEST_MODE = true.
Symbols are immutable string whose value is itself, for example:

  • favorite_framework = :rails
  • :rails.to_s == "rails"
  • "rails".to_sym == :rails
  • :rails == "rails"  # => false

Variables, Arrays, Hashes

In Ruby, there are no variable declarations, although local variables must be assigned before use and instance and class variables are equal to nil until been assigned. 
It is OK to write:  x = 3; x = 'foo' but it's wrong to write  Integer x=3.
In Ruby, Array and Hash elements can be anyting, including other arrays/hashes, and don't all have to be same type.  As in python and perl, hashes are the swiss army chainsaw of building data structures.
Examples of Array:  x = [1,'two',:three]; x[1] == 'two' ; x.length==3
Examples of Hash:  w = {'a'=>1, :b=>[2, 3]}, w[:b][0] == 2 , w.keys == ['a', :b]

Methods

Everything (except fixnums) is pass-by-reference. Example of methods: 
def foo(x,y)    
  return [x,y+1]
end

def foo(x,y=0)  # y is optional, 0 if omitted
  [x,y+1]       # last exp returned as result
end

def foo(x,y=0) ; [x,y+1] ; end

Methods can be called with:  a,b = foo(x,y) or a,b = foo(x) when optional arg used.

Basic Constructs

In Ruby, statements end with ';' or newline, but can span line if parsing is unambiguous
It is OK to write (as unless cannot end a statement):
raise("Boom!") unless
        (ship_stable)   
But it is wrong to write:
raise("Boom!")
        unless (ship_stable)
Basic Comparisons & Booleans (are just like in all modern programming languges): == != < >  =~  !~  true   false nil  
The usual control flow constructs are:

Strings & Regular Expressions

You should try rubular.com for any regex needs. An example of regex: "string", %Q{string}, 'string', %q{string}
To match a=41 ; the corresponding regex is #{a+1}
Match a string against a regexp (just like with pyhon):
  • "fox@berkeley.EDU" =~ /(.*)@(.*)\.edu$/i
  • /(.*)@(.*)\.edu$/i =~ "fox@berkeley.EDU"
If no match, returned value is false, in case of  match, value is non-false, and $1...$n capture parenthesized groups ($1 == 'fox', $2 == 'berkeley')
/(.*)$/i  or  %r{(.*)$}i   or  Regexp.new('(.*)$', Regexp::IGNORECASE)

Everything is an object; (almost) everything is a method call

Even lowly integers and nil are true objects, and we can write 57.methods57.heinz_varieties, and nil.respond_to?(:to_s) 
Rewrite each of these as calls to send for example:  my_str.length  =>  my_str.send(:length)
  • 1 + 2 is equivalent to 1.send(:+, 2) 
  • my_array[4]  is equivalent to my_array.send(:[], 4)
  • my_array[3] = "foo"   is equivalent to my_array.send(:[]=, 3,"foo")
  • if (x == 3)  ....   is equivalent to if (x.send(:==, 3)) ...
  • my_func(z) is equivalent to self.send(:my_func, z)
In particular, things like “implicit conversion” on comparison is not in the type system, but in the instance methods.

a.b means: call method b on object a, i.e. a is the receiver to which you send the method call, assuming a will respond to that method. It does not mean:  b is an instance variable of a, and does not mean also:  a is some kind of data structure that has b as a member

Understanding this distinction will save you from much grief and confusion.



dimanche 20 mai 2012

SaaS - part II


SaaS Architecture

The Web as a Client-Server System

The Web is a client/server architecture and fundamentally request/response oriented.
Client-Server architecture is a high level architecture where clients and servers are specialized in specific tasks: clients ask questions on behalf of users, servers wait for and respond to questions, serve many clients. 
Client-Server is an architectural pattern, it has another alternative P2P (Peer to Peer) architectures.
A Design patterns capture common structural solutions to recurring problems.
Domain Name System (DNS) is another kind of server that maps names to IP addresses.

Web at 100,000 feet
HTTP (Hypertext Transfer Protocol) is an ASCII-based request/reply protocol used for transferring information on the web 
  • HTTP requests include request method (GET, POST, etc.), Uniform Resource Identifier (URI), HTTP protocol version that is understood by the client, headers for transferring extra informations about the request.
  • HTTP responses from web server include protocol version, status code (2xx all is well, 3xx resource moved, 4xx access problem, 5xx server error), headers and response body.
Early Web 1.0 problem was how to guide a user through a flow of pages as HTTP is stateless. Many options were chosen: 
  • User IP address to identify returning user (problems: public computers, multiple users sharing same IP)
  • Embed per-user junk into URI query string (problems: breaks caching)
  • Cookies: per-user user state can be used for lots of things like customization (My Yahoo), click/flow tracking, authentication (logged in or not), 
A golden rule: don't trust the client, cookies must be tamper-evident.
Which of the previous things could be implemented on the client side? which ones shouldn't be and why?

3-tier shared-nothing architecture & scaling

Dynamic content generation 
In early days, most web pages were (collection of static pages) plain old files. Later, when e-commerce sites appeared, a program was running to generate pages. Originally, templates with embedded code "snippets". Eventually, code become "tail that wagged the dog" and moved out of the Web server. 
Software as a Service
Sites that are really programs have to deal with many things (frameworks support these common tasks):

  • map URI to correct program & function?
  • pass arguments between web site pages 
  • invoke program on server
  • handle persistent storage
  • handle cookies
  • handle errors
  • package output back to user

Sharding vs. Replication
For scaling a Web application is crucial to be able to scale persistence layer. Two techniques are commonly used:
  • Sharding: consists of partitioning data across independent "shards" (e.g. user profile table), it scales great, but bad when operations touch more than one table (e.g. when running join queries),
  • Replication: consists of replicating all data everywhere, this makes running multi-table queries faster, but hard to scale as writes must propagate to all copies which create a temporary inconsistency in data values.  

Summary
Browser requests web resource (URI) using HTTP which is a simple request-reply protocol that relies on TCP/IP. In SaaS, most URI’s cause a program to be run, rather than a static file to be fetched.
HTML is used to encode content, CSS to style it visually
Cookies allow server to track client (e.g. including a handle to server-side information): browser automatically passes cookie to server on each request, and server may change cookie on each response 
Frameworks make all these abstractions convenient for programmers to use, without sweating the details and help map SaaS to 3-tier, shared-nothing architecture

Model-View-Controller 

The MVC design pattern
Separate organization of data (model) from presentation (view) by introducing controllers that mediate user actions requesting access to data, and present data for rendering by a given view.

Web apps may seem obviously MVC by design, but as an architecture other alternatives are possible. 

  • Page Controller where an HTML page is associated in a one to one fashion with a program (e.g. Ruby Sinatra). 
  • Front Controller where a single program handle all user requests and render corresponding view (e.g. J2EE servlet)
  • Template View where code snippets are inserted directly into the view for customizing rendering based on stored data and user request (e.g. PHP).

Models, Databases, and Active Record

In-Memory vs. In-Storage objects
In-memory object are marshaled/serialized into in-storage objects. The later are unmarshaled/deserialized in the first ones.
How to represent persisted object in storage?
Basic operations on objects are Create, Read, Update, Delete (CRUD).
ActiveRecord gives to every model common mechanisms so that it knows how to CRUD itself.

Rails Models store data into Relational Databases (RDBMS) where each Model gets its own database table. A schema is a collection of all tables and their structure.
  • A row is one Model instance, it has a unique value for its primary key, and all rows have similar structure. 
  • Each colon stores value of an attribute of the model.
ActiveRecord vs. DataMapper
DataMapper is an alternative to ActiveRecords that associates separate mapper with each Model to abstract underlying storage system and to be able to work with any RBDMS. DataMapper is used by Google App Engine, it scales very well but can't exploit RBDMS features to simplify complex queries (e.g. join) and relationships.

Controllers, Routes, and RESTfulness

Routes
In MVC, each interaction that user can do is handled by a controller action, i.e. method that handle this interaction. A route maps <HTTP method, URI> to controller action.
For instance, Route "GET /movies/3" is mapped to Action "Show info about movie whose ID=3".
Rails Routing subsystem: 
  • dispatch <method, URI> to correct controller action, 
  • provides helper methods that generate a <method, URI> pair given a controller action, 
  • parses query parameters from both URI and form submission into a convenient hash,
  • built-in shortcuts to generate all CRUD routes (though most apps will also have other routes)
Example of how Rails manage a given user request GET /movies/3/edit  HTTP 1.0
  • Matching route: GET /movies/:id/edit {:action=>"edit", :controller=>"movies"}
  • Parse wildcard parameters: params[:id] = "3"
  • Dispatch to edit method in movies_controller.rb
  • To include a URI in generated view that will submit the form to the update controller action with params[:id]==3, call helper:  update_movie_path(3) # => PUT /movies/3
Representational State Transfer (REST)
The idea behind REST is to create self-contained requests that specify what resource to operate on and what to do to it instead of using cookies, setting them on each user request and do multiple HTTP requests between user browser and Web application.
A service (in the SOA sense) whose operations are like this is a RESTful service: its RESTful URIs name the operations.

Template Views and Haml

Template View pattern
Template View consists of markup with selected interpolation to happen at runtime, it generates HTML that will be consumed by a human. 
In early days, this was the application, e.g. PHP you start writing views than open <?php to write usually, values of variables      or result of evaluating short bits of code. 
An alternative to this pattern is Transform View to generate JSON/XML instead of HTML, in case you application is called as a service by another application.
Template View vs. Transform View
Don't put code into views as MVC advocates thin views & controllers, also it's awkward to put code into Haml pages. An alternative to Haml is html.erb for embedded Ruby templates (just like PHP).
Helpers are methods that prettify objects for including in views, they have their own place in Rails app. 

Summary & Reflections: SaaS Architecture

2008 "Rails doesn't scale"
  • Scalability is an architectural concern that is not confined to language or framework
  • The stateless tiers of 3-tier arch do scale, with cloud computing, just worry about constants
  • Traditional relational databases do not scale, instead various solutions combining relational and non-relational storage (“NoSQL”) scale much better (DataMapper works well with some of them)
  • Intelligent use of caching can greatly improve the constant factors
Architecture is about Alternatives

Summary: Architecture & Rails
Model-view-controller is a well known architectural pattern for structuring apps. Rails codifies SaaS app structure as MVC:
  • Views are Haml or embedded Ruby code, transformed to HTML when sent to browser
  • Models are stored in tables of a relational database, accessed using ActiveRecord
  • Controllers tie views and models together via routes and code in controller methods


samedi 19 mai 2012

SaaS - part I


Engineering Software Vs Engineering Hardware
So many disasters in Software development compared to HW disasters. Cost of upgrade: Very expensive in HW that's why HW designs must be finished (bugs fixed) before manufactured and shipped.
Legacy code  is old SW that continues responding to customer need and you should deal with, but is difficult to maintain and evolve as it's writing with old fashion in software development.
Beautiful code meets customer need and is easily to evolve.

Development processes: Waterfall vs. Agile

Waterfall life-cycle "Big design Up front" very used in HW, that's why used later in SW:
  1. Requirement analysis and specification: meet with customers first and write down his needs
  2. Architectural design
  3. Implementation and Integration
  4. Verification
  5. Operation and maintenance

Each step can be done by different way but in a sequence way: complete current phase then go to next one.
Agile manifesto: continuous improvement instead of long phases, incomplete prototype but with continuous improvement.

  1. Individuals & interactions over processes & tools
  2. Working software over comprehensive documentation
  3. Customer collaboration over contract negotiation 
  4. Responding to changes over following a plan

Assurance


  • Verification (mostly used in HW) answers the question Did you build the thing right? Did you meet the specification?
  • Validation (mostly used in SW) answers the question Did you build the right thing? Is this what the customer wants? Is the specification correct?

Testing apply Divide and conquer: perform different tests at different phases of SW development:

  1. Unit test: single method does what was expected
  2. Module or functional test: across individual units
  3. Integration test: interfaces between units have consistent assumptions (communicate correctly)
  4. System or acceptance test: integrated program meets its specifications 

 In agile development tests are writing before code you wish you had is actually writing. This is what we also cal TDD (Test Driven Development) or Debugging Sucks Testing Rocks.

Productivity

According to Moore's law HW designs are getting bigger (more transistors, memory) and thus lead to bigger SW designs. To improve productivity in HW and SW we come up with following techniques:

  • Clarity via conciseness: write readable code, good syntax (bad one is hard to read), raise the level of abstraction (memory management, scripting languages, meta-programming),
  • Synthesis: instead of doing it your self write tools that generate it for you (code generation)
  • Reuse of other tools built by other people, don't re-invent the wheel, reuse code (functions and procedures, Std libraries, OOP, Design Patterns) 
  • Automation and tools: automated things to replace tedious manual things (e.g. make, cucumber, RSpec)

DRY (Don't Repeat Yourself) don't want to find many places to apply same repair, don't copy and paste code.

Software as a Service (SaaS) 

Traditional SW are binary code installed and runs on local machine in a wholly client fashion. In contrast, SaaS delivers SW & data as service over the Internet via thin/universal program (e.g. browser) running locally.
All traditional SW will be running in cloud in a SaaS way in the few coming years. Why?

  • No install worries about HW capabilities, OS
  • No worries about data losses (everything in the cloud)
  • Easy for group to share and interact with same data
  • One copy of SW, controlled HW environment: no compatibility hassless, simplifies upgrades (no upgrade request sent to users)

Perfect match for SaaS, Agile and Rails as frequent upgrades matches Agile lifecycle, many framework for Agile/SaaS, Rails (was used by twitter in its beginning).

SOA (Service-Oriented Architecture) 

SOA is SW architecture where all components are designed as services instead of having a single monolithic running program (silo program). An application is just a combination of services.
SOA makes it easier to create new apps and customizing apps (e.g. choose a better service).
An example of an SOA architecture is depicted in following figure.
An SOA architecture

Cloud computing

SaaS demands on infrastructure include:
  • Communication: allows customers to interact with service
  • Scalability: fluctuations in demand during new services to add users rapidly
  • Dependability: service and communication continuously available 24x7
How these challenges were addressed in past years: 
  1. Clusters are commodity computers connected by commodity Ethernet switches. They are more scalable and cheaper than conventional servers. Dependability is guarantee via extensive redundancy of resources.
  2. Warehouse Scale Computers: economies of scale pushed down cost of largest data-centers, traditional centers utilized 10 to 20%, the idea of making profit by offering pay-as-you-go use at less than your costs for as many computers as you need.
  3. Utility computing/public cloud computing: offers computing/ storage/ communication with a low cost, as many computers as you want (illusion of unlimited resources), e.g. Google App Engine, Amazon Web Service, Microsoft Azure. 

Fallacies and Pitfalls

Fallacy: if a SW project is falling behind schedule, catch up by adding people. Actually, adding new people make it worst as more communication time is needed, and some time is also needed for these people to learn about the project.
Pitfall: is about ignoring the cost of software design and test.  
Is cost ~ no cost of manufacturing software / data same rationale ? no one should pay for development, just for manufacturing?

SW engineering is more than programming: long lasting / evolvable SW vs. short life of HW led to different development processes.
Software engineering is more than programming


References

It is recommended to read Engineering Long-Lasting Software: An Agile Approach Using SaaS and Cloud Computing to learn more about software engineering through a SaaS approach. Also you may follow Berkeley SaaS course at WebCast. Additional resources can be found at CS169

SaaS book