From IoC to require

Lately I have been working on building out my first non-trivial application with node. It has been a very interesting smashing of my brain cells. Coming from a strictly typed language and moving into a prototype based language has removed a lot of my tools from my tool belt. I can no longer ‘scan assemblies for types’, even if I had an IoC i would be forced to use normal strings rather than Type names. I also no longer have my powerful toolset of Visual Studio and ReSharper (yes its a resource hog, but its damn powerful too). But of all the changes, I think it is the lack of IoC that is hurting me the most.

Last weekend I attended a session at Houston Code Camp on “Beyond AMD” where my good friend talked about the various ways people are extending JavaScript applications. Ryan summed them up into three flavors, you can modify an instance (duck punching), you use a factory (think jQuery $.fn) or you can use a plug in model (think flatiron.js Broadway). It was a great talk that really helped to round out my understanding of developing in JavaScript land.

It wasn’t until I was really rereading through the flatiron docs that it hit me. I really have two ways to get at things. One is by attaching it to a global (it seems that the app object is the preferred one) or I can use require to locate the objects I need. Since require felt right at the time, I started to happily require my way into happiness. That is until my first refactoring that changed a file path. You see require doesn’t have an app root concept so through out my code I am calling require(‘./file’) and then deeper in a nest I have require(‘../../../file’) and different files have different paths. For a moment I thought, Aha! I know what I will do. I will add to require the ability to do something like require(‘~/someFile’) where the ‘~’ was my package root. As I thought it about it having the file system involved at all just didn’t feel right. It seems that for JS the best thing for me to do really is to just extend the ‘app’ global.

It all comes back to the fact that I don’t have a type system in the way that I am used to thinking of it. Its ok, because I can stub this out quite easily for tests. But I do believe that it ALSO means I have to stay extra on guard because I am passing around a global and depending on its presence. It will be very interesting to me to watch how this next round of coding procedes because of this. I hope to report back with more, as I get actual experience doing it. But until then, I am jumping in feet first.

-d

Side Bar: I am drawn to node because I feel it has the module problem solved well. Python has the whole 2.x vs 3.x distutils vs setuptools (easy_install vs pip) etc stuff going on. Ruby has the bundle vs gems thing going on, where node just has npm which is private by default with SEMVER support. I like this. (its still no APT-GET but it works nicely. )

Will do. That appears to be client side. But looks cool. In the post I am discussing the require function call in node vs the require.js client side tool. But AngularJS looks like my cup of tea. Thanks!

EdCh

FYI, check out AngularJS. It supports dependency injection.

Anonymous

How did we get to checking in files? re:RVM its still two tool that I have to learn and understand. never used ‘npm shrinkwrap’ so I can’t comment. Dang it HAF. I just like NPM, we are going to get married and there isn’t anything you can do about it!

haf

That’s a pretty hardline attitude. I can see pros and cons of both; e.g. there’s an adage saying ‘never to check in generated files’, which is similar to how vendoring the packages are; if you can just find good versions, you don’t have to blow up your repo size and pollute your history.

Ruby done the RVM way doesn’t require you to install into a global set of gems; all installations go into gemsets and you can switch between them, so then it’s somewhere in the middle of vendoring and using bundler.

Furthermore, NPM has a command: ‘npm shrinkwrap’ == ‘bundle install’, that generates a transitive closure of your dependencies as a specification file, rather than vendoring them. Is this also FAIL then?

Then there’s the case of writing a lib versus writing an app: with an application you want to follow ceteris paribus, so you vendor your packages. With a lib, on the other hand, you want to follow the package version levelling principle, so you specify dependency ranges. Perhaps node-people simply write apps most of the time and therefore its handier?

Anonymous

Yes it does. I was skeptical at first but now I am sold.

Anonymous

require.js for the server side? I use the shiz out of it for the client side.

Anonymous

I am not YET sold on the cross compiling. I am ok with CoffeeScript to JavaScript but C# to JS feels odd. Plus, I just like the funky nature of JS.

Anonymous

Ok, I finally tried out the Vintage mode. and … its AWESOME.

Anonymous

Correct Ruby has one package installer that is global by default. Then I have to get Bundler to make them private. FAIL. Python, pick your installer, now use the arcane virtualenv stuff to make them private. FAIL. .Net has one crap tastic installer and everything is private by default. good but NuGet is just – so from my view point there is a versus thing. NPM is private by default, works quite well too. I haven’t shopped for an RVM equiv for Node but I imagine it will be nice because, well, they get to learn from everyone else.

haf

Bython has two package installers, correct. But ruby doesn’t, it only has gems. Bundler is for packaging a working set if gems together; it is in Ruby land, what virtualenv is in Python land, what Dir.glob(‘src/**/packages.config’) is in .Net land, so there’s no versus-thing going on in Ruby land. Both Python and Ruby’s gems are private by default when you’re using virtualenvwrapper/virtualenv and RVM respectively.

http://ifandelse.com Jim Cowart

Dru – first of all, thanks for the shout out, I’m honored! I’ve only glanced at the code you passed along to me, but I will say that require.js does have something analogous to an app root – the baseUrl value you can provide in require.config() args. Depending on your folder structure, of course, things could get problematic (i.e. – if you’re trying to load things from outside the baseUrl). If you’re loading in modules that don’t fall under that structure, I would ask myself a couple of questions (at least): 1.) Why do they need to live outside that hierarchy? and 2.) How many of these out-of-hierarchy modules will I be loading in? You may have very legitimate reasons to answer “yes” to #1, but given the nature of how Fubu works it’s magic on the server side, the same paradigm probably doesn’t translate well into loading js resources on the client side (that’s an arm-chair-quarterback opinion, not too deeply thought out yet). The reason why asking #2 is important is that you’ll ideally want to optimize your require modules using r.js – which can crawl the dependency tree and bundle modules together in one (or several small/targeted) compressed/minified js file. In even a non-trivial app, the difference this kind of optimization can make is *significant*. At least there’s some initial food-for-thought that you can smack me upside the head with until I get a chance to look at your code more….

I’d be interested to hear what your views would be on using a C# to JS converter. Something like Script# or SharpKit. Best of both worlds or a Frankenstein?

Richard Anaya

I strongly recommend looking at requirejs. I too have thought about how to architect nodejs applications that were non-trivial. The cloud9 project really enlightened me to how a big project could be modularized in a consistant way both client side and server side.