Wednesday, June 17, 2015

Source Location, i.e. Where the heck is this method defined?

Just a short one for now.

Most of the time, if you are working on a well defined project, it's pretty easy to find where a function is if you want to change/tweak it. You can look in the class where it is defined and/or see if there are any mixins or decorators.

Sometimes, it can be downright impossible to tell.

Enter source_location

Fire up your rails console and put in the following (for a class method :search on User)

User.method(:search).source_location

if you have an instance method

User.new.method(:search).source_location

This should give you something like the following

["/Users/yourdrive/Projects/prokect/vendor/cache/thinking-sphinx-9b71ce0f7d9d/lib/thinking_sphinx/search_methods.rb",

 367]

This should at least give you some idea of what is going on...

Sunday, June 14, 2015

Mixins in ES6

I had been looking for a good way to do mixins in ES6.

Looks like I finally found one.

http://raganwald.com/2015/06/10/mixins.html

Essentially,

create the mixin as a const

Use Object.assign to add the properties to the Class

const BookCollector = {
  addToCollection (name) {
    this.collection().push(name);
    return this;
  },
  collection () {
    return this._collected_books || (this._collected_books = []);
  }
};

class Person {
  constructor (first, last) {
    this.rename(first, last);
  }
  fullName () {
    return this.firstName + " " + this.lastName;
  }
  rename (first, last) {
    this.firstName = first;
    this.lastName = last;
    return this;
  }
};

Object.assign(Person.prototype, BookCollector);
(I am copying and pasting this for personal reference in case the original site link goes down).

Thursday, May 28, 2015

The perils of over testing

Test Driven Development (TDD) is a great thing. It allows us to write code "safe" in the knowledge that if we accidentally break something in another part of the system, we will be alerted to it and can re-write or fix accordingly.

It's such a good thing that often in large teams people will insist on this idea of 100% code coverage (i.e. every piece of working code has a corresponding test). Also, some people are compelled to test every single permutation and variation of how someone will access their program/website.

TDD does have some costs however. Some are evident, but others not so.

Cost 1 - Tests take time to run
True, automated testing is faster than manual testing, but they do take time to run. This time means every time you make a change to the code, you need to wait for the suite to finish running in order to feel that your code is "safe" for deployment.

Most of this time is a necessary evil.

A lot of it is unnecessary...

Should you write a feature that checks to see that a form is disabled if a text box is not checked? Well, it depends...

If this is essential to the end user getting to a process, then possibly yes.

If this is just to check a possible error condition that has little or no bearing on the final result, then possibly no.

You could maybe write it as you are developing a feature and then remove it when you are done.

Or else you can write an Object Oriented JS component (FormDisabler) and then test its logic with Jasmine.

Bear in mind that testing JavaScript in a feature will bring up the whole stack which takes time. Time is valuable.

One analogy is that testing is like packing for a trip. You might think that you will need to bring everything you have to cover every possible situation, but really you probably only need an overnight bag with a couple of changes of clothes. The cost is that the more you bring, the more you have to carry.

Cost 2 - Brittleness
Over testing can lead to a very brittle code base where one small change can lead to many hours of fixing broken tests. In Agile development you will constantly make changes to the code base and often what is wanted in the end is not what is expressed in the beginning.

If you test every single possible scenario, then a small business change can lead to a domino effect of broken tests.

The key is to identify what aspects/methods of a feature are most important and to test those.

Classes should be made bulletproof, but not features.

Martin Fowler's Test Pyramid is a good guide.

http://martinfowler.com/bliki/TestPyramid.html

 Summary
At the end of the day, you have to use your brain and judgement to determine what tests are important and what tests are not. It is a subjective thing and can vary from team to team (and application to application). Back to the packing analogy, you should only pack what you need for the trip. If you are writing something mission critical that can never go down and the slightest mistake can lead to potential loss of human life, then by all means go for 100% test coverage. On the other hand, if a mistake in part of your app means a comment or review might not get posted, then test accordingly.

Sunday, April 12, 2015

ECMAScript 6

Today is a rather significant one for me as JavaScript/Rails programmer because Sprockets (https://github.com/rails/sprockets) upgraded to version 3 meaning I can now use the Sprockets-es6 gem (https://github.com/josh/sprockets-es6) to transpile ES6 JavaScript to ES5.

Now to those that didn't understand the last paragraph, here's what it means...

The language we commonly call JavaScript is actually formally known as ECMAScript (http://en.wikipedia.org/wiki/ECMAScript). Since 2009 all the major browsers have been interpreting ECMAScript version 5. In fact they mostly still do.

Version 6 is due to be formalised any day now (well, June 2015) which means that a whole new slew of functionality is due to be added to the language (class constructors, formal inheritance, fat arrows, etc...). Browser makers will start implementing these new features once the spec is complete.

All of this sounds great, but for 2 things

1) I want to start using ES6 today
2) Even if the newly released browsers did come out today, people are not all going to upgrade their browsers as soon as the new ones come out. Typically there is about a year lag before a new feature (or set of features) has enough critical mass to be used with any confidence.

So what can we do?

Well thankfully there are transpilers which can take most of the features of ES6, and rewrite them as ES5. The 2 main ones are Babel (https://babeljs.io/) and Traceur (https://github.com/google/traceur-compiler). For various reasons, I chose to use Babel (because I found their resulting code more readable and because their gem, Sprockets-es6, seemed to have the easiest to add to our project flow). (Basically Traceur didn't work with Phantom which is what we use for testing and is actually running ES4!).

Unfortunately, sprockets-es6 had a dependency on sprockets 3 which was in beta up until this weekend.

And now it's out of beta!

As I write this I am just testing it out on our develop server and hopefully I will go live with it soon.

Happy days.

If you want an example of what can be done with ES6, you can mess around with it here.

http://www.es6fiddle.net/


Monday, September 15, 2014

Opal - Ruby to JavaScript compiler

So I just found out about the Opal Ruby to JavaScript compiler and I am very intrigued.

http://opalrb.org/

So for a few years now, the Ruby community has been encouraged to use CoffeeScript as a JavaScript "alternative" (http://coffeescript.org/) but for some reason, as an avid JavaScript programmer, it never appealed to me. CoffeeScript offers a small amount of syntactic sugar on top of JavaScript, but it never seemed worth the learning curve for me to take it on. I don't actually mind JS's brackets (as they let you know where things begin and end cleanly) and significant white space in a programming language has always seemed like a bad idea too (it's bad enough that a misplaced semicolon can stop a program from running properly, but try searching for an extra white space character you can't even see!).

Opal on the other hand, is actually Ruby compiled to JavaScript (not Ruby/Python-ish syntax). It looks, feels, and even smells like Ruby because it is. The JavaScript it generates might be a little more verbose than that generated by CoffeeScript, but that's because it has to do more (Ruby and JavaScript are separate languages in the proper sense, not different dialects). It does however compile out its classes using the module pattern which means it is safely scoped (http://toddmotto.com/mastering-the-module-pattern/).

It also has a "Native" bridge to interact with regular JavaScript which helps maintain clean separation (http://opalrb.org/docs/interacting_with_javascript/) as well as RSpec support for testing. It even supports method_missing.

In any case, there are many other interesting things about it, which I won't go into here.

It will be interesting to see where it leads...

PS I see Opal as being more like ASM.js (http://asmjs.org/) than CoffeeScript. It can actually use a quite limited subset of JS in order to be functional.