Static typing for the dynamically typed guy

It’s been a while since I’ve used a programming language with some kind of type checking. My transition from the C++ world to the Ruby one was difficult at first. That changed quickly as I became fluent and recognize the productivity benefits of a language with a REPL and just enough meta programming to be dangerous. In my world static typing had died. It was only getting in the way. Fact is, I’d always had the luxury of working in small teams.

Recently I’ve started to come back around to the other side. Type systems don’t have to be verbose and clumsy and can often be very powerful, just take a look at Haskell. They can also make a big difference on big, fast moving teams with diverse levels of experience and varied product requirements. Like any tool they can get in your way if used improperly. Used well types can be great in helping you make large code changes by “leaning on the compiler”. They can provide an additional level of documentation. They can even help you eliminate bugs.

I present to you here a couple of basic rules that you can use to make static typing work for you. This guide is aimed at the developer who’s been writing much more JavaScript than Java.

Use the most appropriate type

It’s very easy to write highly functional programs in a statically typed language using only a handful of the built in types. The Java String class for instance is well supported by the language, and is very powerful. It can be tempting to use it to represent all kinds of domain specific knowledge, especially because Strings are often used to represent information coming from an external source.

But code that only uses a small set of types is taking limited advantage of the type system. If all types are the same then the type declarations provide limited documentation. It’s easy to mix and match values and produce invalid programs. Often the more appropriate type will include behaviour that is specifically relevant to its use cases.

Be conservative

When choosing the most appropriate type, one should be conservative. This means choosing the type that most accurately represents the data, but also the type that offers the smallest interface. This includes when referring to a type and also when instantiating it. An interface is more conservative than an implementation because it offers no behaviour. A Java primitive is more conservative than its boxed equivalent because it is incapable of representing the absence of a value (i.e. null). A sum type is more conservative than a union type because it is capable or representing fewer values.

Convert to a more appropriate type as soon as possible

At the frontier of any application there is a boundary between the code and the outside world. Where inputs such as network traffic, file data or keystrokes are converted from their native form into application data. This layer is sometimes called the trust boundary. Outside this trust boundary exists a wild west of data: unstructured, malicious, invalid or even corrupt.

Information enters through this boundary via simple primitives like integers, arrays of bytes or strings. Validating and then converting this information into a more appropriate type at the trust boundary prevents problems being propagated through the code base. Code bases that don’t take this strategy often end up being larger as more code has to be written defensively and processing has to be duplicated.

Consider adding a type

Often the types available in your language are insufficient to represent information relevant to your domain. This does not mean that you should settle for the simplest type available. Consider adding a type that is named appropriately to describe what it contains. Create as little as an interface as needed to make the type usable for your domain. Domain specific types can be invaluable when requirements change. Even if a type does not offer any behaviour adding a value type to hold it can aid in readability and ease of refactoring.

Types should be small, simple and immutable

When creating new types a good strategy is to keep them a simple as possible. A good rule of thumb is that a type should have a single responsibility. Smaller types are easier to compose together to provide value and tend to change less frequently. In general you should try to create types that cannot be mutated since this makes code harder to reason about.

Conclusion

As always with any set of guidelines there are exceptions to the rule. There are times when you’ll need to sacrifice these rules to achieve certain goals. For instance: immutable types can often be less performant than mutable ones. One could also take these rules to extremes and end up with an explosion of types. There is no harm in reminding the reader to be pragmatic. Nevertheless these rules if followed should result in a code base that can change more easily while remaining correct. That reveals the absence of certain types of bugs. That is easier to understand.

1 note

"I actually attack the concept of happiness. The idea that - I don’t mind people being happy - but the idea that everything we do is part of the pursuit of happiness seems to me a really dangerous idea and has led to a contemporary disease in Western society, which is fear of sadness. It’s a really odd thing that we’re now seeing people saying “write down 3 things that made you happy today before you go to sleep”, and “cheer up” and “happiness is our birthright” and so on. We’re kind of teaching our kids that happiness is the default position - it’s rubbish. Wholeness is what we ought to be striving for and part of that is sadness, disappointment, frustration, failure; all of those things which make us who we are. Happiness and victory and fulfillment are nice little things that also happen to us, but they don’t teach us much. Everyone says we grow through pain and then as soon as they experience pain they say “Quick! Move on! Cheer up!” I’d like just for a year to have a moratorium on the word “happiness” and to replace it with the word “wholeness”. Ask yourself “is this contributing to my wholeness?” and if you’re having a bad day, it is."

Hugh Mackay (via sirmitchell)

2,715 notes

terminally-incoherent:

Waaaaaaaaat?

4 notes

Facebook and GooglePlus Javascript SDK sign in with Devise + RoR

Recently I added a modal sign in and sign up dialog to a Rails application that allowed for sign in using Facebook or Google as well as via email. This dialog can appear any time a user attempts to perform a protected action, allowing them to sign in and continue without losing any data.

To make this work I had to implement Google and Facebook sign in using the new javascript SDK provided for both platforms. The old style authentication redirects when successful which means any in memory session state is completely lost. This means forms are cleared, event handlers are rebound and any work in progress has to be done again.

Before I explain the difficulties we had getting this to work with I’ll explain briefly how OAuth works with respect to devise.

Typical OAuth workflow

Most sites implement this kind of workflow by opening a popup window pointing at their oauth request url (e.g: /oauth/facebook/). This sets up the initial state of the session using a cookie and redirects to the login page providing a url to it to redirect the user again once they’ve authenticated.

If authentication is successful, an oauth token is generated and stored in a cookie and the user is redirected to the callback url. The callback url hits the devise stack and verifies that the token is real by asking Facebook to verify it. If everything checks out execution dips into your application code and the user is created or looked up by some identifiable piece of information.

Client Side workflow

The new SDKs provided by Facebook and Google have changed this and allow for much greater flexibility. Facebook documents its new login workflow here http://developers.facebook.com/docs/howtos/login/getting-started/ and Google documents theirs here: https://code.google.com/p/google-api-javascript-client/wiki/Authentication.

Both APIs have a simple method which expects a callback. The callback is executed indicating whether authentication was successful and it’s up to you what you do with that information. This allows for greater flexibility and smoother transitions into an authenticated step.

Getting it to work with Devise

There are a number of gotchas with using the client side approach, some of them related to possible bugs and my difficulty in interpreting just how the OAuth devise gems work.

OAuth Gem Version

Omiauth OAuth2 version 1.1 recently introduced CSRF validation for the authentication workflow. Unfortunately this breaks client side validation since there is no request component.

For now I suggest downgrading those gems like so:

# NOTE: omniauth-oauth2 breaks client authentication, see here:
# https://github.com/intridea/omniauth-oauth2/issues/20
gem 'omniauth-oauth2', '~> 1.0.0'
# NOTE: omniauth-facebook 1.4.1 breaks SDK authentication, see here:
# https://github.com/mkdynamic/omniauth-facebook/issues/73

The comments will give any future reader of your Gemfile an indication of what they need to do to lift the version restrictions on the omniauth dependencies.

Google OAuth2 Token Validation

The current omniauth-google-oauth2 gem will try to validate your access token with a different server and request format to the one required by the new javascript SDK. For the time being you can use our the forked version (here)[https://github.com/pivotal-geostellar/omniauth-google-oauth2/tree/client_login].

Performing Authentication

For the Facebook SDK we use the following code:

FB.login(function(response) {
  if(response.authResponse) {
    $.ajax({
      type: 'POST',
      url: '/users/auth/facebook/callback',
      dataType: 'json',
      data: {signed_request: response.authResponse.signedRequest}
      success: function(data, textStatus, jqXHR) {
        // Handle success case
      },
      error: function(jqXHR, textStatus, errorThrown {
        // Handle error case
      })});
  }
, scope: 'email'});

For the Google authorization we do the following:

var scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile';
gapi.auth.authorize({client_id: 'client id', scope: scope}, function(result) {
    if(result && !result.error) {
      $.ajax({
        type: 'POST',
        url: '/users/auth/google_oauth2/callback',
        data: {code: result},
        dataType: 'json',
        success: function(data, textStatus, jqXHR) {
          // Handle authorized case
        },
        error: function(jqXHR, textStatus, errorThrown) {
          // Handle error case
        }
      });
    } else {
      // Handle unauthorized case
    }
});

Both of these calls hit the OAuth callback endpoint to verify the access tokens obtained by the user. If authentication succeeds you’ll get the typical devise+OAuth workflow and a session omniauth.auth cookie with the appropriate details.

0 notes

The Healthy Gemfile

Often when working on ruby projects that use Bundler, I see Gemfiles that look like this:

gem 'rails',          '3.0.15'
gem 'rest-client',    '1.3.0'
gem 'subexec',        '0.0.4'
gem 'uuidtools',      '2.1.1'

The string on the right hand side of each gem specification is a fixed version specification. If you ask bundler to update any of these gems, it will make a bit of noise but those gems listed will essentially stay the same.

The typical reason for structure a Gemfile like this is to prevent changes in dependent software from causing compatibility issues or to reduce the chance of bugs or unexpected behaviour.

This strategy is problematic for several reasons: it keeps your project stale, makes it difficult to maintain overall project security and worse yet, can provide a false sense of security. There is a much better and simpler way of writing a Gemfile that will preserve the health and consistency of your dependencies.

Problems with this approach

The first and most obvious problem is that your application will quickly become out of date. The Ruby community moves very quickly and introduces changes quite frequently which means that if you freeze your gems, you may find it very difficult to upgrade later. This problem can be compounded when a security patch is made and the version of the gem you’re using is no longer supported.

A more subtle problem is that the gems listed in your Gemfile have dependencies, and those dependencies may not necessarily be required with as strict a version specification. If you do a bundle update, some of those dependencies could change and break your application.

If you’re the more conservative type, and you’re developing an application that might be in use for some time, you may also be aware that the gems you depend on might not be available forever. They could be removed from the repository, or even altered in a way that breaks your app. If this concerns you there is a much better solution.

A better way of managing your gems

Use Gemfile.lock to document required versions

The true manifest of gem versions is the file Gemfile.lock which is updated by bundler any time your gemset is changed. This should be kept in source control, so that whenever you or your collaborators run bundler install, the exact versions of every gem are installed.

Document dependency problems

If a particular gem version breaks your project, by introducing a bug or a change to it’s API, lock it using the appropriate modifier.

Typically an API change is only introduced in a major version change (e.g: 3.x.x becomes 4.x.x). You can make sure your gem stays reasonably up to date but doesn’t change to the next major revision using a pessimistic restriction like so: '~> 3.1.1'.

If the next minor version introduces a bug which breaks your project, lock the gem version with a specific revision (e.g '3.1.1').

Whenever you restrict a gem version, document why! Sometimes the errors causes by a dependency change can be quite obscure and waste significant time. I like to leave a comment like so:

# TODO: Remove version lock when this bug http://github.com/project/issues/311
# is fixed. It breaks the transmogrification adaptor because of a missing method.
gem 'descartes', '3.1.1'

Use tests to drive out dependency issues

The best indication that a gem has broken your project or needs to be managed more carefully is a test suite with good coverage. With good coverage, particularly integrations tests you can be confident that whenever you do a bundle update everything still works.

If your gems are kept up to date most of the time and you use source control it will be quickly obvious which version changes introduced a bug.

Be hesitant to specify a version restriction

And finally, don’t specify a version restriction in your Gemfile without a very specific and well understood reason. It can often be tempting to simply list the version of the gem available at the time or to lock the version if you come from a more conservative background. A healthy Gemfile has few version restrictions, explains clearly the ones it has and comes attached with a lockfile for quick deployment and development.

0 notes

How to make your site less secure #3: Require only part of a password. This makes it difficult to recall a password using muscle memory, encourages people to write down passwords or use weaker ones which are easier to remember the position of characters from.

For bonus points, give out hints at how long the password required is so it’s easier to find accounts with a weaker password.

How to make your site less secure #3: Require only part of a password. This makes it difficult to recall a password using muscle memory, encourages people to write down passwords or use weaker ones which are easier to remember the position of characters from.

For bonus points, give out hints at how long the password required is so it’s easier to find accounts with a weaker password.

0 notes

How to make your site less secure #2: Make sure people have to enter security details with an onscreen keyboard.

It’s easier for people to see you type your password, it’s often quite clumsy and difficult to use - which discourages stronger passwords and it’s just as easily logged by a mildly sophisticated trojan or rootkit.

0 notes

How to make your site less secure #1: Ask security questions that can be easily answered with a quick Internet search.

Also for bonus points: exclude people who’s siblings have 2 or 3 character names!

How to make your site less secure #1: Ask security questions that can be easily answered with a quick Internet search.

Also for bonus points: exclude people who’s siblings have 2 or 3 character names!

0 notes

Yesod on Mac OS X with Homebrew

Had a bit of difficulty getting Yesod to work with my Homebrew install of Haskell and Postgres. Got this slightly cryptic error:

can't load .so/.DLL for: pq (dlopen(/usr/local/Cellar/postgresql/8.4.4/lib/libpq.dylib, 9): no suitable image found. Did find: /usr/local/Cellar/postgresql/8.4.4/lib/libpq.dylib: mach-o, but wrong architecture)

To make things work I had to install the 64 bit version of the Haskell compiler.

brew install ghc --devel

Then I had to install yesod-platform, persisten-postgresql and yesod-test in one go. Installing them separately seemed to cause breakages:

cabal install yesod-platform persistent-postgresql yesod-test

0 notes

0 notes