Yesod – first pages

June 14, 2016 Web frameworks, Yesod No comments

We already have a working environment – it’s the best possible moment to get started with teh codez!

Yesod, like many other web frameworks, has a Model-View-Controller architecture. It has a central controller instance which routes requests to proper handlers. In the scaffolded site these routes are conveniently stored in config/routes file. If you didn’t make any changes to it, it probably looks like this:

/static StaticR Static appStatic
/auth   AuthR   Auth   getAuth

/favicon.ico FaviconR GET
/robots.txt RobotsR GET

/ HomeR GET POST

/comments CommentR POST

it contains a lot of magic. It is a syntax which is later processed by Template Haskell to generate quite some code that guarantees type safety. For starters let’s skip first two routes and focus on the rest.

The syntax is fairly simple: route route-type handled-methods. So, for example, line /comments CommentR POST means: from all requests directed to route /comments accept only POST requests and define type CommentR which will be used to redirect to this route (in Yesod routes are type-safe, so you need types for them). Additional feature is that route handlers are invoked automatically – in out example it would be postCommentR function (you can find its implementation in scaffolded site in Handler/Comment.hs file. Handler names are created from lowercase method name concatenated with route type name. It’s a nice example of Convention over Configuration pattern, and it frees us from writing an awful amount of code which we don’t really want to write (at least I don’t). Adding R postfix (shortcut for Route) to route type is also a Yesod convention, which does not need to be kept, but may help others read your code.

Ok, enough chit-chat, let’s write some codez!

First, let’s edit config/routes. Just stuff in there /projects ProjectsR GET. Great, now your code doesn’t compile and complains about lack of getProjectsR function. Let’s fix it the way scaffolded site does it – create a Handler/Projects.hs file with the following content:

module Handler.Projects where
import Import

import Yesod.Form.Bootstrap3()

getProjectsR :: Handler Html
getProjectsR = defaultLayout $ do
    setTitle "Projects"

add the handler to <code>Application.hs</code> as well:

-- Import all relevant handler modules here.
-- Don't forget to add new modules to your cabal file!
import Handler.Common
import Handler.Home

-- new one
import Handler.Projects

as the comment says, you also need to add this file to your <code>.cabal</code> file to this block:

        exposed-modules: Application
                     Foundation
                     Import
                     Import.NoFoundation
                     Model
                     Settings
                     Settings.StaticFiles
                     Handler.Common
                     Handler.Home
                     Handler.Comment
                     Handler.Projects

that’s important, because if you won’t do that, you’ll get an unknown symbol error at startup. Now run stack exec -- yesod devel and go to localhost:3000/projects. The result might not be very impressive (an empty page), but you might guess that it’s already using our route – it has our title (not very impressive either).

That’s all nice and fine, but if you take a look at the page source, you’ll notice that there’s quite some stuff already, including Bootstrap and jQuery. Where did it code from?
If you recall the handler code, it was really simple: getProjectsR = defaultLayout $ do setTitle "Projects". All the magic lies in defaultLayout call. It picks up a default (for the project) layout file and fills it with data from the argument. This default template layout is split between two files: default-layout.hamlet and default-layout-wrapper.hamlet, both in templates directory. .hamlet is an extension for Hamlet files, which are Haskell form of HTML templates, serving roughly the same purpose as Jade, Jinja or Smarty. I’ll cover Hamlet templates in greater detail in the next post – for now let’s just treat a .hamlet file as a HTML without closing tags. Since pretty much everything seems to be in default-layout-wrapper.hamlet, you might wonder why are there two – this is generally related to the purposes – default-layout-wrapper.hamlet is roughly a static structure that will be filled with data, while default-layout.hamlet is more dynamic and can contain some conditional logic and similar stuff. Additionally, CSS and JavaScript files with the same name are automatically added to default-layout.hamlet (this is because default-layout.hamlet is treated as a usual Widget. We’ll talk about Widgets later in the series). Go ahead, change something – for instance, add a new div in default-layout.hamlet and some text in default-layout-wrapper.hamlet and refresh the page. See how default-layout.hamlet was inserted in place of ^{pageBody pc} ?

If you don’t, go ahead and call stack exec -- yesod devel. Remember that stack might be able to reload Hamlet templates, but is not really able to hot-swap actual Haskell code, so you might need to restart it, especially when adding new files.

That’s it for today – in the next episode we’re gonna create a template view for our projects.

Stay tuned!

Environment setup

June 7, 2016 Web frameworks, Yesod No comments

Let’s start with the tooling.

Obviously something can go wrong during development, so version control is a must. I prefer Git, but if you use Mercurial, Bazaar or Subversion (or whatever else) it’s fine as well. If you wanna feel super-haskellish, try out Darcs.

As for OS platforms, this series will cover Windows and Linux setups. I’m going to use Windows 10 and CentOS Linux (a RHEL derivative), so if you’re using Ubuntu you may need to adjust the code a little (e.g. use apt-get install instead of yum install), but there shouldn’t be bigger differences – if you’re using something like Slackware, Arch or Gentoo, I assume you already know what to do better than I do. As for Windows, it should work out-of-the-box on all reasonably new machines (say, starting from Windows Vista up).

A few more words about the setup before we dive into the code: while working code examples can be found on my GitHub repository dedicated for this blog: https://github.com/Lewerow/SlightlyBetter, I do have quite a complex local setup, involving a version control server and a continous integration server. I use a local setup of Gitlab along with Gitlab-CI on a CentOS sitting inside a VirtualBox. While this sounds pretty complex, it’s not that bad – I’m going to cover automatic creation of such setup in one of future series.

Anyway, let’s get back to Haskell and Yesod stuff. Setting up a simple web page from existing template (“scaffolded”) is generally quite easy, but might require installing some extra packages. First let’s install  Stack – a build tool for Haskell projects. Installation is typical for your platform (installer for Windows, .rpm packages for CentOS, .deb packages for Debian) and is described in detail in Stack documentation.

Only thing that still remains to be done is executing following commands (beware: it takes some time):

stack new TaskOrganizer && cd TaskOrganizer
stack build yesod-bin cabal-install --install-ghc
stack build

Assuming that everything went fine (which is not obvious on Linux machines – you might need to install additional development packages, like build-essential, zlib1g-dev or libpq-dev – watch out, .rpm development packages usually use -devel instead of -dev used in .deb packages), you now have a working Yesod site. Check it out by running stack exec -- yesod devel and going to http://localhost:3000/ with your browser. If it worked – congratulations! Your first Yesod app is up.

Next week we’re gonna do more stuff – add custom routes for projects. Stay tuned!

And don’t forget to add your project to Git! (For example by git init . && git add --all . && git commit -m "Initial commit")

Yet Another Web Framework?

June 5, 2016 Web frameworks, Yesod No comments

If you’re writing a web application, it is likely that you aren’t going to write all the code from scratch – there is a tremendous amount of work that was already done dozens of times and you don’t really want to repeat it. So you’re going to pick a framework – and it isn’t easy! Rails, Hanami, Django, Flask, Express, KOA, Spring, Play, Lift, Phoenix, Revel  and dozens of others, most of which I’ve never heard about. Why create next one? There are several reasons, language focus being one of the strongest. Rails, Hanami, Padrino and Volt focuses on Ruby. Django, Flask and Pyramid on Python, Express, KOA and Synth on JavaScript (specifically Node.js), Spring and Struts on Java, Lift and Play on Scala (though Java/Scala framework division is a little artificial, since Play works on Java as well), Phoenix on Elixir, Revel on Go etc. Another one is the focus on programming model – most of the popular frameworks use MVC (Model-View-Controller) approach, but some – like Lift, Wicket or Asta4D – use different, View-First approach. Of course, there are also lots of different reasons – changing some old paradigm, using new language feature, solving a problem other frameworks have for long time or simply “writing a more elegant framework”.

In such a jungle, choosing the best framework for the job is vitually impossible, so we settle for “good enough”. And this usually boils down to choosing one of the most common frameworks – Rails, Django or Express, possibly Spring if your company is Java-inclined, or something from Go if you’re feeling hippie (or maybe Elixir or some other new language if you’re feeling super-hippie).

And it is usually a good decision – not a perfect one, but good. You know the language, you know the framework, you can write code fast. Cool, eh?

Well, yeah. If you’re writing a one-team app or a prototype, or at least an app in write-and-forget mode, then choosing Rails, Express or Django is a great choice. But for bigger projects, well… sure, it’s possible. But if you lack discipline your Sentry (you have Sentry or something similar hookend up on your production servers, right?) will start shouting with things like undefined is not a function or 'NoneType' object is not callable. If you have discipline things are slightly better and you simply have to maintain gazillions of unit tests for all weird scenarios where internal flow was not valid or user data was not properly sanitized or whatever. And you usually have to either maintain these unit tests forever, or drop features. What’s worse, these UTs usually aren’t well-written
and are an obstacle for refactoring, while you would want them to aid it. Sounds familiar? Well, bad news then – it’s not a problem of the framework.

There are two main reasons for such situation: one is obviously the development process – with a perfect process and discipline, you can go really far with any tool you want. But using the right tool makes it easier (or at least forces you to keep the discipline). Dynamically typed languages, like Ruby, Python or JavaScript are great for small projects, small teams or prototypes, but on bigger ones well-known problems appear: interfaces. It’s hard to define interface on a language that roughly checks the syntax of the source code – of course, possible, but much harder than in statically typed languages with compilers – like Java, Scala, C++ or Haskell. There are attempts to create things like “JavaScript with types” (TypeScript, Flow), but this simply doesn’t work – it’s a part added artificially to a language after it’s already in the field, and doesn’t really make people happy.

Statically typed languages, on the other hand have another problem – they usually have a steep learning curve, and some of them (for example, Java) require quite some boilerplate to create reasonable applications. Scala with its type-safe approach is much better in the area of enforcing interface contract – value of features like type-safe database queries is hard to overestimate. Scala is quite a new language (started in 2001) with a very interesting paradigm and full power of the JVM behind – it’s really worth checking out.

However, in this series I’m going to focus on a different alternative to Ruby/Python/JS frameworks. One that is considered arcane and hard and has quite a steep learning curve if you have mostly a dynamically-typed background. I’m going to show you how to develop a simple web application in Haskell, by using its arguably biggest web framework – Yesod. If type-safe database access sounds like “wow”, then you’re going to like it – in Yesod even routes are type-safe. And since I’m lazy, I believe in tools imposing as much useful restrictions as possible. Since I believe type-safe stuff to be incredibly useful, I’ve decided to give it a try. This is the first post of a series of introductory posts to Yesod (occassionally also with Haskell insertions). Fun starts next week.

Stay tuned!

Greetings and salutations

June 5, 2016 Meta No comments

Welcome to SlightlyBetter – a blog about doing IT stuff slightly better than before.

I’ll mainly focus on automating testing, deployment and configuration, but there will be also occasional posts about programming and software development in general. I hope you’ll be able to learn something and develop software that is slightly better than you developed before you visited me.

First series, about using Yesod to implement a simple web application starts next week

Stay tuned!