Comparing Dynamic and Static Language Approaches to Web Frameworks



Similar documents
Project Group Applied Functional Programming

Rails 4 Quickly. Bala Paranj.

Advanced Tornado TWENTYONE Advanced Tornado Accessing MySQL from Python LAB

YouTrack MPS case study

Deep in the CRUD LEVEL 1

Evaluation. Chapter 1: An Overview Of Ruby Rails. Copy. 6) Static Pages Within a Rails Application

Building Dynamic Web 2.0 Websites with Ruby on Rails

Progressive Enhancement With GQuery and GWT. Ray Cromwell

CSE 373: Data Structure & Algorithms Lecture 25: Programming Languages. Nicki Dell Spring 2014

Web Frameworks. web development done right. Course of Web Technologies A.A. 2010/2011 Valerio Maggio, PhD Student Prof.

So you want to create an a Friend action

The Django web development framework for the Python-aware

UNIVERSITY OF MALTA THE MATRICULATION CERTIFICATE EXAMINATION ADVANCED LEVEL COMPUTING. May 2011

CS169.1x Lecture 5: SaaS Architecture and Introduction to Rails " Fall 2012"

Gluing things together with Haskell. Neil Mitchell

Outline. Lecture 18: Ruby on Rails MVC. Introduction to Rails

A Model of the Operation of The Model-View- Controller Pattern in a Rails-Based Web Server

Advanced Functional Programming (9) Domain Specific Embedded Languages

The programming language C. sws1 1

Ruby on Rails is a web application framework written in Ruby, a dynamically typed programming language The amazing productivity claims of Rails is

Lecture 9. Semantic Analysis Scoping and Symbol Table

Design and Functional Specification

Clojure Web Development

Pentesting Web Frameworks (preview of next year's SEC642 update)

How to Build a Model Layout Using Rails

Avaya Inventory Management System

WHITE PAPER. Peter Drucker. intentsoft.com 2014, Intentional Software Corporation

What s really under the hood? How I learned to stop worrying and love Magento

Ruby on Rails Secure Coding Recommendations

Intruduction to Groovy & Grails programming languages beyond Java

THE ROAD TO CODE. ANDROID DEVELOPMENT IMMERSIVE May 31. WEB DEVELOPMENT IMMERSIVE May 31 GENERAL ASSEMBLY

Web Framework Performance Examples from Django and Rails

Ruby on Rails. Computerlabor

Web development with Lua Programming Language

1/20/2016 INTRODUCTION

10CS73:Web Programming

Developers Guide. Designs and Layouts HOW TO IMPLEMENT WEBSITE DESIGNS IN DYNAMICWEB. Version: English

Moving from CS 61A Scheme to CS 61B Java

Web Programming Languages Overview

Enterprise Recipes with Ruby and Rails

DTD Tutorial. About the tutorial. Tutorial

Parrot in a Nutshell. Dan Sugalski dan@sidhe.org. Parrot in a nutshell 1

New Generation of Software Development

GUI and Web Programming

Developing ASP.NET MVC 4 Web Applications MOC 20486

1. Comments on reviews a. Need to avoid just summarizing web page asks you for:

HOUR 3 Creating Our First ASP.NET Web Page

Guides.rubyonrails.org

How to Choose the Right Web Design Company for Your Nonprofit

Hello. What s inside? Ready to build a website?

INTRODUCTION TO OBJECTIVE-C CSCI 4448/5448: OBJECT-ORIENTED ANALYSIS & DESIGN LECTURE 12 09/29/2011

Ruby on Rails. Object Oriented Analysis & Design CSCI-5448 University of Colorado, Boulder. -Dheeraj Potlapally

Two new DB2 Web Query options expand Microsoft integration As printed in the September 2009 edition of the IBM Systems Magazine

opalang - Rapid & Secure Web Development

Drupal CMS for marketing sites

Introduction to Ingeniux Forms Builder. 90 minute Course CMSFB-V6 P

RESTful Rails Development. translated by Florian Görsdorf and Ed Ruder

Content Management System (Dokument- og Sagsstyringssystem)

Programming in Access VBA

Chapter 7: Functional Programming Languages

HOW TO CREATE THEME IN MAGENTO 2

Intellect Platform - The Workflow Engine Basic HelpDesk Troubleticket System - A102

Programming Languages

Agent s Handbook. Your guide to satisfied customers

Grails 1.1. Web Application. Development. Reclaiming Productivity for Faster. Java Web Development. Jon Dickinson PUBLISHING J MUMBAI BIRMINGHAM

Lecture 3 ActiveRecord Rails persistence layer

Developing ASP.NET MVC 4 Web Applications

Jos Warmer, Independent

Comp 411 Principles of Programming Languages Lecture 34 Semantics of OO Languages. Corky Cartwright Swarat Chaudhuri November 30, 20111

Dynamic website development using the Grails Platform. Joshua Davis Senior Architect Cognizant Technology Solutions

Page Editor Recommended Practices for Developers

web frameworks design comparison draft - please help me improve it focus on Model-View-Controller frameworks

Slides from INF3331 lectures - web programming in Python

How to set up a scoring algorithm and automatic triggers for Qualtrics measures

KITES TECHNOLOGY COURSE MODULE (C, C++, DS)

MASTERTAG DEVELOPER GUIDE

Semantic Analysis: Types and Type Checking

MEAP Edition Manning Early Access Program Nim in Action Version 1

Instructor: Betty O Neil

Top 10 Oracle SQL Developer Tips and Tricks

Chapter 12 Programming Concepts and Languages

Apache Thrift and Ruby

JRuby Now and Future Charles Oliver Nutter JRuby Guy Sun Microsystems

Semester Review. CSC 301, Fall 2015

The Guide to: Marketing Analytics"

Developer Guide To The. Virtual Merchant

Using XACML Policies as OAuth Scope

Smartphone garage door opener

DSL Design. Model Transformations. Model Transformations. Language g Implementation Strategies

Transcription:

Comparing Dynamic and Static Language Approaches to Web Frameworks Neil Brown School of Computing University of Kent UK 30 April 2012

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Comparing Dynamic and Static Language Approaches to Web Frameworks Neil Brown School of Computing University of Kent UK 30 April 2012 Slides with blue headers are original slides, these grey pages are notes pages. I should point that out that my opinion in this talk is biased: I ve been using Rails for a few years, and suffering with maintaining our Rails sites. I believe in static typing, powerful compilers, and making as many errors as possible into compile-time errors (hence I like Haskell). So I was interested to try Yesod and see how far it was able to use these static features, compared to Rails, for the same end result. That led to this talk. I m partly comparing Yesod to Rails, but I m more interested in comparing the use of Haskell s static approach (and Template Haskell meta-programming) to Ruby s dynamic approach, and Yesod and Rails provide good exemplars for this.

Web Frameworks Web Frameworks

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Web Frameworks Web Frameworks Web Frameworks Many websites are ultimately ways to read and write to a database. Web frameworks offer support for common website designs (as in structure/software, not visuals) They are vaguely MVC, with: models stored in database, read by views, written to by forms, with all the wiring to URLs accomplished by routing.

Web Frameworks Web Frameworks

Web Frameworks: Yesod vs Rails Web Frameworks Yesod (Haskell) I m using 1.0 (most recent) Ruby on Rails (Ruby) I m using 2.3 (not most recent)

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Web Frameworks Web Frameworks: Yesod vs Rails Web Frameworks: Yesod vs Rails Yesod (Haskell) Ruby on Rails (Ruby) I m using 1.0 (most recent) I m using 2.3 (not most recent) Ruby is an OOP language with dynamic typing (lots of duck typing). Haskell is a functional language with static typing. Rails uses a lot of dynamic features, Yesod uses a lot of static features, so they are at opposite ends of the scale, yet accomplishing almost exactly the same thing. I gather Rails 3.0 has many changes over 2.3, but we have not yet migrated our sites. I don t think many changes alter this presentation much.

Web Frameworks Software Engineering Challenges To make life easier, need lots of boilerplate helper functions, e.g. username_for_id(int user_id), show_user_url(int user_id) Formulaic, yet specific to each project Best to auto-generate using meta-programming...

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Web Frameworks Software Engineering Challenges Software Engineering Challenges To make life easier, need lots of boilerplate helper functions, e.g. username_for_id(int user_id), show_user_url(int user_id) Formulaic, yet specific to each project Best to auto-generate using meta-programming... The following examples of meta-programming in Ruby and Haskell are not what you would see when you use Rails or Yesod, but I wanted to give a quick idea of the key points of what is happening underneath.

Low-Level Metaprogramming: Ruby Web Frameworks Add new methods at run-time using blocks, something like: class Example def add_method self. class.send(:define_method, :get_const) do return 6 end end end Body is a standard block of code (like closure), added at run-time.

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Web Frameworks Low-Level Metaprogramming: Ruby Low-Level Metaprogramming: Ruby Add new methods at run-time using blocks, something like: class Example def add_method self.class.send(:define_method, :get_const) do return 6 end end end Body is a standard block of code (like closure), added at run-time. The :blah syntax is a symbol, which is like an interned string. The method is added to the Example class at run-time, when you execute add method This dynamic method addition is precisely what makes so many errors run-time errors in Ruby: you can t tell if you re calling a non-existent method at compile -time, because that method might get added later on. It also complicates code completion and so on.

Web Frameworks Low-Level Metaprogramming: Haskell Add source code at compile-time, using Template Haskell functions that return Haskell AST: $(return <$> fund (mkname "getconst") [return $ Clause [] (NormalB $ LitE $ IntegerL 6) []]) Normally use higher-level functions! Run during compilation, then outputted AST is compiled.

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Web Frameworks Low-Level Metaprogramming: Haskell Low-Level Metaprogramming: Haskell Add source code at compile-time, using Template Haskell functions that return Haskell AST: $(return <$> fund (mkname "getconst") [return $ Clause [] (NormalB $ LitE $ IntegerL 6) []]) Normally use higher-level functions! Run during compilation, then outputted AST is compiled. As a Yesod user, you never see any of this! But the point is, the metaprogramming generates a piece of abstract syntax tree (AST) which is then compiled. So the Haskell compiler effectively has several phases: 1. Run any Template Haskell code, between $(blah) (or the quasi-quote notation, which I don t happen to use in this presentation) 2. This Template Haskell produces Haskell AST as its output, which is spliced into that location in the file, as if it had always been there. 3. Compile the complete source file). You can think of Template Haskell as a preprocessor, like the C preprocessor, but it uses full Haskell as its language, produces AST instead of text, and I believe has access to information from the compiler.

Web Frameworks Models

Models Models A model is an entity like user, blog post, comment, etc. Both frameworks offer persistence for models.

Models Models A model is an entity like user, blog post, comment, etc. Both frameworks offer persistence for models. The model persistence usually uses an RDBMS. However, the models are not a relational database.

Rails Models

Models in Rails Models create_table : blog_posts do t t. text : title t. text :content t. integer :author_id end create_table :authors do t t. string :name end

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Models Models in Rails Models in Rails create_table :blog_posts do t t.text : title t. text :content t. integer :author_id end create_table :authors do t t. string :name end This is part of a migration, rather than a model definition as such, but this is how you define new models in Rails. I ve chosen not to cover migrations in this talk, because they are not that interesting in terms of the dynamic/static language divide.

Models in Rails Models class Author < ActiveRecord::Base validates_uniqueness_of :name has_many :blog_posts # implicit public field : name, blog_posts # inherited methods: new, create, save end class BlogPost < ActiveRecord::Base belongs_to :author # implicit public fields : author, title, content # inherited methods: new, create, save end

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Models Models in Rails Models in Rails class Author < ActiveRecord::Base validates_uniqueness_of :name has_many :blog_posts # implicit public field : name, blog_posts # inherited methods: new, create, save end class BlogPost < ActiveRecord::Base belongs_to :author # implicit public fields : author, title, content # inherited methods: new, create, save end The fields that the migration added are then inserted (somehow!) into the classes by Rails. The save (etc) methods store these fields of the model into the database and handle the associations (links to other models) automatically. Note that the classes and migrations and tables in the RDBMS and matched by name: the class Author is stored in the table authors, and BlogPost in blog posts, with Rails handling the conversion from camel-case to underscore. Also, the blog post to author link automatically picks up author id as the reference.

Yesod Models

Models in Yesod Models The models are written in their own file: Author name Text UniqueAuthor name BlogPost author AuthorId title Text content Text

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Models Models in Yesod Models in Yesod The models are written in their own file: Author name Text UniqueAuthor name BlogPost author AuthorId title Text content Text This model file (much like the routes file later on) is not Haskell code (whereas Rails migrations are Ruby code), but instead is a simple Domain-Specific Language (DSL) for expressing models. This DSL is parsed by some Template Haskell, and turned into code for the data types, and for handling the persistence.

Models in Yesod Models Generated code from the models file: data Author = Author {authorname :: Text, authorpassword :: Maybe Text} type AuthorId = Key Author data BlogPost = BlogPost {blogpostauthor :: AuthorId, blogposttitle :: Text, blogpostcontent :: Text} type BlogPostId = Key BlogPost

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Models Models in Yesod Models in Yesod Generated code from the models file: data Author = Author {authorname :: Text, authorpassword :: Maybe Text} type AuthorId = Key Author data BlogPost = BlogPost {blogpostauthor :: AuthorId, blogposttitle :: Text, blogpostcontent :: Text} type BlogPostId = Key BlogPost I ve simplified the types slightly, because the generated types (and keys) are also parameterised by the persistence backend. However, that s a bit too much detail for this talk, and the extra type parameter doesn t alter much during your use of Yesod.

Fetching Model in Rails Models blog_post = BlogPost.find_by_id(blog_post_id) author = blog_post.author Implicit database access (and association load)

Fetching Model in Yesod Models rundb $ do blogpost <- get blogpostid author <- get (blogpostauthor blogpost) Explicit database access (and association load)

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Models Fetching Model in Yesod Fetching Model in Yesod rundb $ do blogpost <- get blogpostid author <- get (blogpostauthor blogpost) Explicit database access (and association load) Having the database transaction in its own monad makes it a bit clearer what will happen on rollback (because there can t have been any IO side-effects).

Models Fetching Model in Yesod rundb $ do blogpost <- get blogpostid author <- get (blogpostauthor blogpost) Explicit database access (and association load) Polymorphic get!

Models Models DB access more explicit (and more fiddly) in Yesod Wrong field error: Rails run-time, Yesod compile-time Each ID has distinct type in Yesod: avoids errors, allows conciseness

Association Helper Function Models Type-safe, no reflection: getand :: Key a -> (a -> Key b) -> DB (a, b) getand parentkey subkeyfunc = do parent <- get parentkey sub <- get (subkeyfunc parent) return (parent, sub) getand blogpostid blogpostauthor

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Models Association Helper Function Association Helper Function Type-safe, no reflection: getand :: Key a -> (a -> Key b) -> DB (a, b) getand parentkey subkeyfunc = do parent <- get parentkey sub <- get (subkeyfunc parent) return (parent, sub) getand blogpostid blogpostauthor This is an example of defining a function that works for any persistent type, without using reflection, etc. This means that you can write functions that are closer to Rails association loading, if you want.

Web Frameworks Routing

Routing Routing Routing is about mapping URLs to actions, and actions to URLs For example:

Routing Routing Routing is about mapping URLs to actions, and actions to URLs For example: http://www.example.com/blog_posts/1 displays blog post with ID=1

Routing Routing Routing is about mapping URLs to actions, and actions to URLs For example: http://www.example.com/blog_posts/1 displays blog post with ID=1 blog_post(1) helper function returns http://www.example.com/blog_posts/1

Rails Routing

Routing in Rails Routing map.resources :blog_posts roughly short for: map.resources :blog_posts, :member => {:show => :get, :edit => :get, :update => :put}, : collection => {:index => :get, :new => :get, :create => :post}

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Routing Routing in Rails Routing in Rails map.resources :blog_posts roughly short for: map.resources :blog_posts, :member => {:show => :get, :edit => :get, :update => :put}, : collection => {:index => :get, :new => :get, :create => :post} The second code portion is not identical to the first, but it s the same idea. The table is the actual output of the first code.

Routing in Rails Routing map.resources :blog_posts roughly short for: map.resources :blog_posts, :member => {:show => :get, :edit => :get, :update => :put}, : collection => {:index => :get, :new => :get, :create => :post} sets up: Helper Stem Method URL Handler blog posts GET /blog posts(.:format) :controller=>"blog posts", :action=>"index" POST /blog posts(.:format) :controller=>"blog posts", :action=>"create" new blog post GET /blog posts/new(.:format) :controller=>"blog posts", :action=>"new" edit blog post GET /blog posts/:id/edit(.:format) :controller=>"blog posts", :action=>"edit" blog post GET /blog posts/:id(.:format) :controller=>"blog posts", :action=>"show" PUT /blog posts/:id(.:format) :controller=>"blog posts", :action=>"update"

Yesod Routing

Routing in Yesod Routing / BlogIndexR GET /new blog post NewBlogPostR GET POST /blog posts/#blogpostid BlogPostR GET /blog posts/#blogpostid/edit EditBlogPostR GET POST

Routing in Yesod Routing / BlogIndexR GET /new blog post NewBlogPostR GET POST /blog posts/#blogpostid BlogPostR GET /blog posts/#blogpostid/edit EditBlogPostR GET POST generates: data Route =... Handler BlogIndexR getblogindexr NewBlogPostR getnewblogpostr, postnewblogpostr BlogPostR BlogPostId getblogpostr, postblogpostr EditBlogPostR BlogPostId geteditblogpostr

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Routing Routing in Yesod Routing in Yesod / BlogIndexR GET /new blog post NewBlogPostR GET POST /blog posts/#blogpostid BlogPostR GET /blog posts/#blogpostid/edit EditBlogPostR GET POST generates: data Route =... Handler BlogIndexR getblogindexr NewBlogPostR getnewblogpostr, postnewblogpostr BlogPostR BlogPostId getblogpostr, postblogpostr EditBlogPostR BlogPostId geteditblogpostr The Yesod routes don t quite have identical URLs to the Rails ones, but they are accomplishing the same idea. Also, the Route type is actually an associated data type of the class instance, but that doesn t really change things.

Routing Routing Both similar, using DSL to generate routing table and helpers Missing handler error: Rails run-time, Yesod compile-time

Web Frameworks Views

Views Views View: code that dynamically generates the actual HTML. Mix of text, HTML markup, and dynamic content, e.g. <p>this page has been viewed <b><% page_count() %></b> times</p>

Rails Views

Views in Rails: Showing a Blog Post Views Controller sets up variables ready for view: class BlogPostsController < ApplicationController def show @blog_post = BlogPost.find(params[:id]) end end

Views in Rails: Showing a Blog Post Views View has interspersed Ruby code: <p> <b>author:</b> <%= @blog_post.author.name %> </p> <p> <b>content:</b> <%= @blog_post.content %> </p> <%= link_to Edit, edit_blog_post_path(@blog_post) %> <%= link_to Index, root_path %>

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Views Views in Rails: Showing a Blog Post Views in Rails: Showing a Blog Post View has interspersed Ruby code: <p> <b>author:</b> <%= @blog_post.author.name %> </p> <p> <b>content:</b> <%= @blog_post.content %> </p> <%= link_to Edit, edit_blog_post_path(@blog_post) %> <%= link_to Index, root_path %> The Rails view is loaded in, substituted and compiled at run-time.

Yesod Views

Views in Yesod: Showing a Blog Post Views Handler sets up variables ready for view: getblogpostr :: BlogPostId -> Handler RepHtml getblogpostr blogpostid = do (blogpost, author) <- rundb $ do blogpost <- get404 blogpostid author <- get404 (blogpostauthor blogpost) return (blogpost, author) defaultlayout $(widgetfile "blog_post_view") The last line loads and compiles the view.

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Views Views in Yesod: Showing a Blog Post Views in Yesod: Showing a Blog Post Handler sets up variables ready for view: getblogpostr :: BlogPostId -> Handler RepHtml getblogpostr blogpostid = do (blogpost, author) <- rundb $ do blogpost <- get404 blogpostid author <- get404 (blogpostauthor blogpost) return (blogpost, author) defaultlayout $(widgetfile "blog_post_view") The last line loads and compiles the view. The get404 function is one that fails (and exits the handler, rendering a 404 page) if the database item is not found. The last line is a Template Haskell call which renders the view from the blog post view file (i.e. the file is explicitly named, rather than implicitly named by the controller action, as in Rails). The Template Haskell call reads in the file at compile-time, generates Haskell code based on the file, and then compiles that. So the template is completely compiled into code, and thus the splicing process is potentially optimised.

Views in Yesod: Showing a Blog Post Views View is Hamlet (indentation-based HTML), with interspersed Haskell code: <p> <b>author: #{authorname author} <p> <b>title: #{blogposttitle blogpost} <p> <b>content: #{blogpostcontent blogpost} <a href=@{editblogpostr blogpostid}>edit <a href=@{blogindexr}>index

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Views Views in Yesod: Showing a Blog Post Views in Yesod: Showing a Blog Post View is Hamlet (indentation-based HTML), with interspersed Haskell code: <p> <b>author: #{authorname author} <p> <b>title: #{blogposttitle blogpost} <p> <b>content: #{blogpostcontent blogpost} <a href=@{editblogpostr blogpostid}>edit <a href=@{blogindexr}>index Hamlet is like HTML, but has no closing tags, and uses indentation to indent tag-scoping. The #{blah} markup encloses Haskell code that returns text (which is then HTML escaped). The @{RootR} markup encloses a Haskell expression of Route type, and generates the URL for that item.

Views Views Hamlet is odd choice (and not necessary) Bad code in view error: Rails run-time, Yesod compile-time Haskell s field names are annoying (blogposttitle vs title)

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Views Views Views Hamlet is odd choice (and not necessary) Bad code in view error: Rails run-time, Yesod compile-time Haskell s field names are annoying (blogposttitle vs title) Haskell s field names (you must have unique field names across the program, not just unique per class like in OOP languages) are caused by the type inference in the language. It s a hot topic right now, with several proposals on how to fix it, but it does get irritating in applications like this.

Web Frameworks Forms

Forms Forms HTML forms are needed to enter data

Rails Forms

Forms in Rails Forms Controller sets up variables for view: class BlogPostsController < ApplicationController def edit @blog_post = BlogPost.find(params[:id]) end end

Forms in Rails: Editing a Blog Post Forms Form is a view with form-related code/idiom: <% form_for(@blog_post) do f %> <p> <%= f.label : title %><br /> <%= f.text_area : title %> </p> <p> <%= f.label :content %><br /> <%= f.text_area :content %> </p> <%= f.submit Update %> <% end %>

Forms in Rails: Editing a Blog Post Forms Submitted form comes back to controller: class BlogPostsController < ApplicationController def create @blog_post = BlogPost.find(params[:id]) if @blog_post.update_attributes(params[:blog_post]) redirect_to (@blog_post) else render :action => "edit " end end end

Yesod Forms

Forms in Yesod: Editing a Blog Post Forms Handler gets variables and creates form, which is passed to view: geteditblogpostr :: BlogPostId -> Handler RepHtml geteditblogpostr blogpostid = do blogpost <- rundb (get404 blogpostid) ( result, bpform) <- fst <$> runformpost (renderdivs (blogpostform blogpost)) case... of _ -> defaultlayout $(widgetfile "blog_post_edit")

Forms in Yesod: Editing a Blog Post Forms Form is generated from code: blogpostform :: BlogPost -> AForm App App BlogPost blogpostform blogpost = BlogPost (blogpostauthor blogpost) <$> areq textfield " Title " ( blogposttitle blogpost) < > areq textfield "Content" (blogpostcontent blogpost) Then spliced into view: <form method=post action=@{editblogpostr blogpostid}> ^{bpform} <input type=submit>

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Forms Forms in Yesod: Editing a Blog Post Forms in Yesod: Editing a Blog Post Form is generated from code: blogpostform :: BlogPost -> AForm App App BlogPost blogpostform blogpost = BlogPost (blogpostauthor blogpost) <$> areq textfield " Title " (blogposttitle blogpost) < > areq textfield "Content" (blogpostcontent blogpost) Then spliced into view: <form method=post action=@{editblogpostr blogpostid}> ^{bpform} <input type=submit> The splice syntax shown here, ˆ {blah}, splices in HTML content, which is not escaped.

Forms in Yesod: Editing a Blog Post Forms Submitted form comes back to handler: posteditblogpostr :: BlogPostId -> Handler RepHtml posteditblogpostr = geteditblogpostr

Forms in Yesod: Editing a Blog Post Forms Submitted form comes back to handler: geteditblogpostr :: BlogPostId -> Handler RepHtml geteditblogpostr blogpostid = do blogpost <- rundb (get404 blogpostid) ( result, bpform) <- fst <$> runformpost (renderdivs (blogpostform blogpost)) case result of FormSuccess blogpost -> do rundb (replace blogpostid blogpost ) redirect (BlogPostR blogpostid) _ -> defaultlayout $(widgetfile "blog_post_edit")

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Forms Forms in Yesod: Editing a Blog Post Forms in Yesod: Editing a Blog Post Submitted form comes back to handler: geteditblogpostr :: BlogPostId -> Handler RepHtml geteditblogpostr blogpostid = do blogpost <- rundb (get404 blogpostid) ( result, bpform) <- fst <$> runformpost (renderdivs (blogpostform blogpost)) case result of FormSuccess blogpost -> do rundb (replace blogpostid blogpost ) redirect (BlogPostR blogpostid) _ -> defaultlayout $(widgetfile "blog_post_edit") The runformpost function both creates the form, and attempts to parse the results of the form, which are stored in the environment (technically: in the state monad part of the Handler monad stack). Thus you can act on form success during the POST submit action, or just show the view during the original GET action. On the one hand, it makes sense for the GET and POST handler to be the same because they tend to share a lot of code (one builds the form from content, the other tears the form apart to get similar content back), but it is a little bit subtle that runformpost has these two different functionalities.

Forms Forms Single-handler is neat trick in Yesod, but overall Yesod generally takes more code to do forms Bad form field error: Rails run-time, Yesod compile-time

Final Notes Errors Yesod has compile-time errors where Rails has run-time errors How likely are mis-spelt names, etc? Flipping Rails plurals! Use of strong typing (in Yesod or Rails) confers other benefits, e.g. protection from XSS through data-tagging.

2012-05-01 Comparing Dynamic and Static Language Approaches to Web Frameworks Final Notes Errors Errors Yesod has compile-time errors where Rails has run-time errors How likely are mis-spelt names, etc? Flipping Rails plurals! Use of strong typing (in Yesod or Rails) confers other benefits, e.g. protection from XSS through data-tagging. Yesod has a different type for plain text and HTML data. The #{blah} splice takes plain text, and escapes it, whereas the ˆ {blah} splice takes HTML and does not escape it. Conversion between the types must be done explicitly (typically with pre-supplied functions). I gather Rails 3.0 has similar protection, but done dynamically.

Final Notes Development Want fast edit-test cycle in dev mode: Rails: reload source files before handling each request Yesod: watchdog recompiles after every change

Final Notes Overall Summary You can accomplish very similar results with static and dynamic approaches Metaprogramming and DSLs have lots of practical applications in web frameworks Lots of interesting uses of Haskell s type system in Yesod Rails: easy start, high maintenance 1 Yesod: tougher (even taking Haskell into account), lower maintenance (e.g. easier to refactor) 2 1 Speaking from experience! 2 Educated guess!