Category Archives: Uncategorized

The frustrations of opensource

I spend a lot of time “re-inventing the wheel”, usually due to being blocked or frustrated by the wheel I’m trying to use.

Frustrations and roadblocks that occur when dealing with opensource software can often get in the way of writing software, and when that’s your job, you can’t just wait a few months for an issue to be resolved.

A great example of how something minor can become a major frustration has been happening for a while now. clone, a nice little lib that lets you pass pretty much anything in, and get a cloned version of it out. I use it in many of my modules, but it has an issue:

https://github.com/pvorb/node-clone/pull/46

clone checks if the input is a Buffer, and if it is, it will clone the buffer. This is required functionality of the module. The issue is, even if you never mention Buffer anywhere else in any of your code, or your dependencies, the fact that clone *can* deal with Buffer, means browserify *will* include it.

Programmatically, this  is fine, but the browserify Buffer implementation is reasonably large (40kB!), and adds a significant weight to any browserify bundle that contains it.

I realised that trying to obscure Buffer from browserify wasn’t going to cut it, and decided that a better solution would be to solve this in browserify.

The actual problem

The root of the issue is that browserify should NOT add Buffer on clone’s behalf. Clone does NOT need Buffer unless some OTHER module is using it.

I opened an issue in browserify explaining the issue, and suggesting a flag be added to solve the issue:

https://github.com/substack/node-browserify/issues/1228

The solution proposed involved adding a field to the “browserify” object in a modules package.json, that would tell browserify what builtins this module uses, but should not be bundled because of it.

The discussion finally petered out with basically “That sounds hard”. I had a dig through browserify, looking to add this myself. I was able to figure  out that it was actaully going to be insert-module-globals that needed some work, but it didn’t have access to the package.json, so the option would need to be passed, and the code was so unreadable that I eventually just gave up.

The TL;DR:

some modules, like clone need Buffer to create Buffers, but only if another module passes it in.

  • if no other module in the bundle references Buffer, clone does not need it, so it should be omitted.
  • if another module in the bundle references Buffer, clone may need it, and it will be available, because the other module will have caused it to be added.
  • Browserify needs a way to be told when a module shouldn’t cause a builtin to be bundled, just like peerDependencies.

 

Advertisement

Make stylus more nodey

Today I wanted to break some stylus files out into their own module, and I wanted to be able to require a stylus module in the same way I would require a node module.

I tryed:

npm i my-styles-module

And then:

@require my my-styles-module

Which of course didn’t work, but there is a way.

As explained here, you can tell stylus other directories to look in for imports and requires, if it can’t find it in its working directory.

I’m using gulp to build my stylus, so all that was required was to add:

...
.pipe(stylus({
include: ['../node_modules']
})
...

And now stylus works just like node.

How to check if something is an array.

Every once in a while, I see someone talking about how to check if a thing is an array. I’ve been through a few stages of how to write an array detection utility myself.

Stage 1; “instanceof is the best!”

I’ll just check if object instanceof Array! Woohoo!

And then I came across this: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

Huh, arrays from other frames are not instances of the Array constructor in this frame. I guess that makes sense, since it isn’t an instance of this frames Array.

Stage 2; “instanceof is the worst!”

Righto, guess I’ll use the solution provided.

One problem:

The suggested solution relies on checking a string that gets spit out from Object.prototype.toString.call().

That’s great, except for this:

Object.prototype.toString.call(Array.prototype);
// -> [object Array]

Cool so now your array detection function will detect Array.prototype as an array, which it isn’t.

http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4

Shudup spec, Array.prototype isn’t an array, that would be fucking stupid. Anyway Array.prototype.instanceof Array returns false, as you would expect, because it literally isn’t an instance of Array. If you make your own constructor, you wouldn’t expect it’s prototype to be an instance of it, would you?

Really, if you’re checking that something is a thing based on some random string you pulled from a function on a different constructor… you’ve gotta expect problems.

Stage 3; “Array-detecting libraries are stupid”.

There is a huge amount of noise on the internet around this topic, and it is all noise. You will never make a perfect one-size-fits-all .isArray, Even Array.isArray() won’t work for array-like objects that people intend to be used in place of arrays. In the end, to quote greenday…

It doesn’t even matter.

Think about what you are actually trying to check for. If you have an API that takes an array, just use instanceof Array. Who cares if it doesn’t work across frames? Thats a rare case, and if you need to talk across frames, you will probably know that you’re doing it; Convert the array to a local instance before you give it to your API. Sure it won’t work with that Hipster new library that gives you SuperArrays, but that isn’t important, because the new hotness will come and go. Your library should support JavaScript.

Don’t be afraid to use instanceof, for arrays or any other object. It is an extremely robust way of ensuring an object will look and behave how you expect. It isn’t perfect, but it’s how JavaScript was meant to be used.

The takeaway:

  • instanceof Array is NOT harmful.
  • array detection libraries are stupid, think about what you actually need to check, and check for that.

Samsung Series 9 Touchpad Fixes

Simply put, Samsung software is shit. The touch pad hardware is excellent, and even the drivers for it are great, but the software that ships to configure it is extremely limited.

Have you ever wished you could do crazy things like 3-finger-touch right click? Or maybe use the touch-pad while pressing keys? Probably not right? That all sounds WAYYY too hard and crazy for a user, or at least that’s what Samsung thinks.

Luckily you can change pretty much everything, the Elan driver is really feature-rich and configurable, if you know what to do.

So, to convert your touch-pad from usable to awesome:

1. Open regedit

  • windows+r
  • type ‘regedit’, press enter, 
  • Accept the prompt

2. Go to the honey pot of touchpad settings

  • HKEY_CURRENT_USER
  • Software
  • Elantech
  • Smartpad

3. CHANGE ALL THE THINGS!

Want three finger right-click?

  • change Tap_Three_Finger to 1

Want two finger middle-click?

  • change Tap_Two_Finger to 2

(You can obviously swap 2 finger and 3 finger by swapping their values if you’re weird)

Want to be able to use the touch-pad while typing?

  • Change DisableWhenType_Enable to 0

Just got windows 8.1 and lost the ability to have normal scrolling?

  • Change SC_Reverse_Enable to 0

As you can see there’s a whole ton of settings that can be tweaked. I’m yet to play with everything I’ll want to tweak.

 

Gedi, an absurdly powerful model API

logo

Firstly, what’s gedi?

git: https://github.com/gaffa-tape/gedi
npm: https://npmjs.org/package/gedi

Gedi is model API wrapper. It Allows you to get and set, and remove to/from an object, and bind to changes that occur due to sets/removes.

Simple usage:

    // Set up the models data
    var model = new Gedi({
        thing: 2,
        lifeforms:{
            dogs:[
                {
                    name: "scruffy",
                    age:8
                },
                {
                    name: "spot",
                    age:4
                }
            ],
            users:[
                {
                    name: "bob",
                    age: 20
                },
                {
                    name: "john",
                    age:45
                }
            ]
        }
    });

    // get
    model.get('[thing]'); // --> 2

    // set
    model.set('[thing]', 5);

    // get after set
    model.get('[thing]'); // --> 5

    // bind to [thing]
    model.bind('[thing]', function(event){
        // this callback is called when [thing] changes.
        // event.getValue() returns the value of [thing]
    });
    

You can throw a parent path on the end of get/set/etc.. to make all bindings relative to it.

    model.get('[dogs]'); // --> undefined

    model.get('[lifeforms/dogs]'); // --> Array of dogs.

    // here, [dogs] will be relative to [lifeforms]
    model.get('[dogs]', '[lifeforms]'); // --> Array of dogs.
    

Why square braces?

Because gedi is more powerfull than just an object watcher.

you can pull data out via expressions…

    model.get('(last [lifeforms/dogs]).name'); // --> "spot"
    

And even bind callbacks to expressions…

    model.bind('(last [lifeforms/dogs]).name', function(event){
        // this callback is called when [lifeforms/dogs] changes.
        // event.getValue() returns the value of (last [lifeforms/dogs]).name
    });
    

However there was one thing I’d always thought would be awesome, and i’ve recently made some pretty big changes to how gedi works under the covers to allow.

    // Set the last item in [lifeforms/dogs] to a different dog
    model.set('(last [lifeforms/dogs])', {name: "ellie", age: 2});
    

Gedi can now keep track of paths throughout the execution of an expression, and perform useful opperations using the resulting path.

This is pretty exciting to me, expecially for how it can be used in gaffa.

You can also perform opperations on the result of a filter/map/slice/concat/etc.. eg.

(fyi, the syntax for an anonymous function in gedi is {param1 param2 paramN functionBody})

remove all items in an array that match an expression.

    model.remove('(filter [dogs] {dog (> dog.age 7)})', '[lifeforms]');
    

set properties on all items across multiple arrays that match an expression. (TO RIDICULOUS, AND BEYOND!)

    model.set('(map (filter (concat [dogs] [users]) {item (> item.age 5)}) {item item.label})', 'old!', '[lifeforms]');
    

And of course, any changes made using expressions cause model events to fire at the right paths.

The Blackberry Z10, So much right, so much wrong…

I’ve been using a blackberry Z10 as my main phone for about 2 weeks now, having used the Dev Alpha B for a few months before that, and I’ve pretty much made up my mind about it. My previous phone was a Galaxy Nexus, so that’s what I’ll be comparing it to mostly.

Hardware:

The good:

  • The button-less face is excellent. I’ve already forgotten how to unlock other phones.
  • Nice high res screen.
  • Decent performance (only ever really noticeable when playing 3D games, which run well).
  • Decent battery life, I get a day’s heavy use out of it without issue.
  • The back cover is nice and grippy, you can stick it on a dash and it won’t slide around (if you drive carefully).
  • The camera is excellent.

The bad:

  • The screen is kinda small.. Not iPhone small, that would be ridiculous, but it’s smaller than my GNex, even though the phone its self isn’t any smaller.
  • Looks like an iPhone. While this will help BB steal iPhone users, it makes me slightly embarrassed to be seen with it. I don’t see how they could not get sued by Apple, it actually is very similar, unlike previous phones that were a ‘copy’. It’s quite boring to look at.
  • The volume buttons feel cheap, and I don’t really know what the middle button is for.
  • The plugs are on the side. This is sometimes a good thing, but mostly it looks weird.
  • It has pulg*s*. It doesn’t need a HDMI out, the phone isn’t being pushed as a media device, so why dedicate an ugly port to it?
  • The ports are positioned weirdly, mostly on the body of the phone, but partly into the back cover.

Software:

the good:

  • The browser. It is the best. Ever. Literally nothing else is as good. Chome for desktop? Excellent, still not as good as the BB browser. I’m not kidding, it is better than Chrome, for both viewing and developing web applications.
  • Cascades (or whatever) is awesome. Once you swipe things around on this phone, you can’t help but accidentally swipe other phones, usually resulting in Google now. Something came in to the phone? Slide up, hold, slide to the side if you want a preview of the notification.
  • App-specific notifications. OMG they are awesome. Something happened in an app? Red icon. Something happened in an app in a folder? Red icon. Give the engineer who came up with this a raise, I love it.
  • the Hub is great, no matter what happened, it can always be found in the hub.
  • The app switcher is really fluid for switching between 2 apps.
  • The word flicking keyboard is a good idea.

the bad:

  • The apps. There aren’t enough. This should seem like an obvious, unavoidable issue, as with any new phone, but this phone should be an exception. Blackberry does not leverage their browser enough. Why isn’t there a way to turn any website into a chrome-less app?
  • Maps. They suck. Practically unusable. The app lags all the time. Why the hell would they not just use Google maps?
  • The phone has crashed probably 30 times since I’ve had it. At least once a day, but I have a feeling its probably more often than I realise.
  • Apps cannot run in the background. This is a big issue as it stops apps like llama (for android) working, which is a big issue because the phone is never in the right profile.
  • The phone is never in the right profile (like I just said). It is constantly going off when you don’t want it to, and never ringing when you need it to. This is because I don’t manually change the profile, because I am a human and any ‘smart’ phone should do this for me.
  • The keyboard needs the long-press-for-symbols feature that android has. Things like question marks shouldn’t be difficult to input.
  • It has a shit lock-screen. The only option is a password. Patterns people!

Development:

the good:

  • The browser, as mentioned, is amazing. The development experience is not just bearable, but actually BETTER than Chrome for desktop! The profile tab has better info than Chrome. Apps run fast, every feature you could want is available.
  • Native development: who cares, this is 2013.

the bad:

  • Java. Seriously? you need Java to create a web-app for this phone? Why? BB really needs to improve the tooling around turning web-apps into BB apps.

In summary, I really like some of the ideas that went into this phone, but I don’t think I can live with it. The few apps it does have are either crippled by the lack of OS support, or are just not very good. An example: Google talk lets you have only 1 account, and it notifies you of messages, even when you are using another device to converse with your contact. There is no Google latitude.

I realise that some will say “Well just make the missing apps yourself!” which is true, I could, and probably should do this, but I just don’t have the time.

Should you buy it?

If you are a previous BB user you will probably love it.

If you are a previous iPhone user you will probably hate it for the wrong reasons

If you are a previous Android user you will probably love some of the features, then get annoyed with the lack of applications.

Personally, I’m torn, If i go back to android, I will miss some of the amazingly good features like swipe to  unlock, swipe to notifications, and swipe to do pretty much anything. I will miss the excellent browser. That said the maps, lack of apps, Google talk, and frequent crashes are really getting to me..

Basically…. I lied; I’m not sure yet.

A BB/Android blend would be the perfect phone.