A Foolish Manifesto

fREWdiculous!

New Stuff in Log::Contextual 0.004000

I just released Log::Contextual 0.004000 and it has a handful of great features.

It now supports arbitrary levels, so where before you simply had:

  • trace
  • debug
  • info
  • warn
  • error
  • fatal

Now you can have any levels by just saying

1
use Log::Contextual -levels => [qw(lol wut zomg)], ':log';

which would import functions for log levels lol, wut, and zomg.

But the really exciting thing is that now you can make a base class of Log::Contextual and set defaults for all of the different import options:

1
2
3
4
5
6
7
8
9
10
package MyApp::Log::Contextual;

use parent 'Log::Contextual';

use Log::Log4perl ':easy';
Log::Log4perl->easy_init($DEBUG);

sub arg_logger { $_[1] || Log::Log4perl->get_logger }

1;

The $_[1] in arg_logger is whatever logger the user passed in when they said “use MyApp::Log::Contextual -logger => …”. You can choose to allow them to override the logger like I did above, or you can force them to always use the logger that you set.

You can also use the arg_levels, arg_default_logger, and arg_package_logger methods, but I doubt anything other than arg_logger and arg_levels will be common.

Anyway, I hope people find this release as exciting as I do; I know it will make my code a lot nicer.

  • 1 Comment
  • Filed under: Uncategorized
  • DBIx::Class Extended Relationships

    Since the dawn of time DBIx::Class relationships were simply a set of columns related to each other via equality. For the most part this is good enough, but DBIx::Class aims at 100% power for all databases (unlike some other ORMs… :-) .)

    In May what we internally called “extended relationships” was added to DBIx::Class. (docs here) Basically this allows you to use the full power of SQL::Abstract to define your join conditions. Just today I finally had a chance to use it. My join condition is simply “tableA.user = tableB.user OR tableA.shared = 1″. Here is how I defined it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    has_many output_devices => '::OutputDevice', sub {
       my $args = shift;
       
       my $shared = { "$args->{foreign_alias}.shared" => 1 };
       return ([
          { "$args->{foreign_alias}.user" =>
             { -ident => "$args->{self_alias}.user" } },
          $shared,
       ],
       $args->{self_rowobj} && [
          { "$args->{foreign_alias}.user" => $args->{self_rowobj}->user },
          $shared,
       ]);
    };

    There are two interesting things to point out.

    It’s a coderef. This is so that we can parameterize various salient bits, like the aliases for the tables and, if it exists, the row object. There are a few other things passed, but I didn’t need them here.

    The other interesting thing is that instead of returning a single join condition, I returned two conditions. The first is simply a join condition, which might be used if you were to call search or related_resultset. The second is a where clause to allow more basic SQL to be used when you already know one side of the join clause. So instead of doing something silly like “JOIN Foo ON Foo.bar = me.bar WHERE me.bar = 1″ we can simply use “FROM Foo where Foo.bar = 1″. Also note that a handful of helpful methods in DBIx::Class (create_related and friends) require the second condition to be defined and fairly simple.

    It is definitely more verbose to use join conditions like this, but having the ability is great.

  • 1 Comment
  • Filed under: Uncategorized
  • Event Loops are better than while (1)

    One of the projects that I worked on last year had a number, five I think, of background daemons. Basically the way we implemented this was by making a DoesRun role that looked something like the following:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package Lynx::SMS::DoesRun;

    use Moose::Role;

    requires 'single_run';

    has period => (
       is => 'ro',
       required => 1,
    );

    sub run {
       my $self = shift;
       while (1) {
          $self->single_run;
          sleep $self->period;
       }
    }

    no Moose::Role;

    1;

    And then a typical Runner class looked something like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package Lynx::SMS::Runner::Voice;

    use Moose;
    use Log::Contextual::SimpleLogger;
    use Log::Contextual qw( :dlog :log ),
      -default_logger => Log::Contextual::SimpleLogger->new({ levels => [qw( warn error fatal )]});

    with 'Lynx::SMS::DoesRun';
    has schema => (
       is => 'ro',
       required => 1,
    );

    sub single_run {
       my $self = shift;

       log_debug { 'Processing voice messages' };
       my $guard = $self->schema->txn_scope_guard;
       while ($self->schema->resultset('MessageChild')->voice->unsent->not_blocked->count) {
          ...
       }
       $guard->commit;
    }


    no Moose;

    __PACKAGE__->meta->make_immutable;

    1;

    And lastly, a script using the runner looked like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #!/usr/bin/env perl

    use 5.12.1;
    use warnings;
    use rlib;

    use Lynx::SMS::Runner::Voice;
    use Lynx::SMS::Schema;
    use Config::ZOMG;

    my $config = Config::ZOMG->open(
       name => 'Lynx::SMS',
       path => '.',
    );

    my $voicer = Lynx::SMS::Runner::Voice->new(
       schema => Lynx::SMS::Schema->connect( $config->{Model}{DB}{connect_info} ),
       period => 60, # seconds
    );

    $voicer->run;

    Anyway, that was all well and good, but at some point things would die and the whole thing would come crashing down, so then we started adding an eval around the call to run in the script, and then I thought, “someone must have done this before…” So I asked in the #catalyst channel on irc.perl.org and rafl pointed out that this is what event loops (POE being the oldest and probably most popular) are great at.

    So I updated the run method in the DoesRun role, so now it looks like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    sub run {
       my $self = shift;
       my $j = AnyEvent->condvar;
       my $w = AnyEvent->timer(
          interval => $self->period,
          cb => sub { $self->single_run },
       );
       $j->recv;
    }

    Ok, cool enough, it basically does the exact same thing as before except it never dies. But then I had an idea, on a server with 16 Gigs of RAM and a dual quad-core CPU five fat perl daemons is hardly an issue. But when developing it’s certainly a hassle to have to start them all up myself. So why not combine them and have them all run in the same process? Cake! I made the following Runner class to do the magic:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package Lynx::SMS::Runner;

    use Moose;

    has tasks => (
       is => 'ro',
       default => sub { [] },
    );

    sub run {
       my $self = shift;
       my $j = AnyEvent->condvar;

       my $x = 0;
       my @tasks = @{$self->tasks};
       @tasks = map {
          my $task = $_;
          AnyEvent->timer(
             after    => ($x++ / @tasks),
             interval => $task->period,
             cb       => sub { $task->single_run },
          )
       } @tasks;
       $j->recv;
    }

    no Moose;

    __PACKAGE__->meta->make_immutable;

    1;

    The after thing is weird, but the idea there is that each task will start at a different time, so things are more likely to run at a different time. Not really important, but it makes the logs easier to follow for me.

    And then here is my script using it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #!/usr/bin/env perl

    use 5.12.1;
    use warnings;
    use rlib;

    use Lynx::SMS::Runner::SMS;
    use Lynx::SMS::Runner::Voice;
    use Lynx::SMS::Runner::Emailer;
    use Lynx::SMS::Runner::Notifier;
    use Lynx::SMS::Runner;
    use Lynx::SMS::Schema;
    use Config::ZOMG;
    use Lynx::SMS::Logger;
    use Log::Contextual
      -logger => Lynx::SMS::Logger->new({
        levels_upto => 'trace',
        format      => '[%d] %m',
      });

    my $config = Config::ZOMG->open(
       name => 'Lynx::SMS',
       path => '.',
    );

    my $schema = Lynx::SMS::Schema->connect($config->{Model}{DB}{connect_info});
    my $runner = Lynx::SMS::Runner->new(
       tasks => [
          Lynx::SMS::Runner::SMS->new(
             schema => $schema,
             period => 1, # seconds
          ),
          Lynx::SMS::Runner::Voice->new(
             schema => $schema,
             period => 1, # seconds
          ),
          Lynx::SMS::Runner::Emailer->new(
             schema => $schema,
             period => 60*5, # 5 minutes
          ),
          Lynx::SMS::Runner::Notifier->new(
             schema => $schema,
             period => 60*60*24, # 1 day
          ),
       ]
    );

    $runner->run;

    One thing that would improve this whole thing would be to capture dies or whatever and log $@ in our standard error logger thing. I haven’t quite figured out how to do that yet, but if someone knows how and comments I’d appreciate it.

  • 1 Comment
  • Filed under: Uncategorized
  • Getting More Done

    Today I purchased 59 Seconds, recommended by Jeff Atwood. I struggle with procrastination as much as anyone else so I’m willing to spend 10 bucks to try to get more done. The author recommends four things to attain a given goal:

    • plan well
    • reward yourself
    • focus on benefits
    • tell people

    I’ve kinda slacked off with Open Source stuff the past year (see the graph at metacpan) and I’d like to remedy that.

    Goal: Participate more

    My overall goal is to participate more (more blogging, more patches/pull requests, more releases and bug fixes for my own modules, etc.)

    The book recommends breaking the overall goal into five for fewer distinct subgoals that are measurable and whatnot, so here are my subgoals:

    Subgoal 1: Do two, public, permanent code related things a week

    For example submit a patch or release a distribution. Pushing to github isn’t permanent :-)

    I think this is pretty feasible. I have a huge backlog of things to do (which I’ll post, semi-prioritised at the end of this post) and I already set aside time on Mondays and Fridays to get stuff done.

    To get this done I’ll work on stuff 2-3 hours on Monday night and 2-3 hours Friday night (assuming nothing is going on.) I also might do stuff Tuesday or Wednesday, but time is scarce with wedding planning. I’ll work on the most important things first, and after that’s done I’ll work on the most fun stuff; the idea being that I can get two things done in a week that way.

    I’ll count this as achieved (though I don’t want to stop) after I’ve done two public things a week for two months straight. I’ll post weekly progress reports every Monday when I start hacking about the previous week.

    My reward for finishing this is to buy myself a new car stereo.

    Subgoal 2: Post two tech related posts to my blog twice a week

    Again, this sounds reasonable. I have a long list of half finished posts that I should just clean up and post. These should keep me busy for a while.

    I’ll have a similar plan for this as I do for Subgoal 1; instead of Monday and Friday I’ll do Tuesday and Sunday. I’m a little nervous about those days as the are mostly booked for the foreseeable future, but what I hope to do is use remaining time on Mondays and Fridays to work on blogging.

    I’ll count this as achieved after I’ve done two tech blog posts a week for eight weeks straight. Weekly progress shouldn’t be necesary :-)

    My reward for finishing this is to buy myself new car speakers.

    Subgoal 3: Get used to using some bug tracker for Open Source work

    Currently I am not very good about using a bug tracker for anything other than work. I’ve used Google’s bug tracker, github’s issue tracker, RT, and am currently toying with ticgit. I need to pick something, get good at it, and stick with it.

    I think I can do this. It mostly takes discipline to pull this off. I need to just add stuff to whatever bug tracker every time I am going to add a new feature, fix a bug, clean stuff up, whatever. I think I’m gonna use ticgit for now since I don’t want to write my own bug tracker yet.

    I’ll count this achieved after every single one of the things from Subgoal 1 that are my own modules use the bugtracker I’ve chosen.

    My reward for finishing this is to buy myself an amp for my car stereo.

    Benefits

    In the book he says you should state three benefits that you would get from finishing your goal. My three benefits are: I would be more respected in the community; my life would be easier as I’d have the things that I’ve been wanting for a while; and lastly, I could get more organized and more quickly ramp up on doing things.

    TODO list

    • DBIx-Class-Helpers – Jnap’s stuff
    • DBIx-Class – Date Math stuff
    • Log-Contextual – subclassable importer
    • DBIx-Class-Helpers – StateHook
    • DBIx-Exceptions – Plan out remaining bits to get done
    • DBIx-Class-Shadow – Plan out remaining bits to get done
    • Git-Conversion-Book – Table of Contents
    • Git-Conversion-Book – Each Chapter (x10?)
    • Object-Exporter – Plan out remaining bits to get done
    • Log-Location – Plan out remaining bits to get done
    • HTML-Zoom-Widgets – Plan out remaining bits to get done
    • Catalyst-ActionRole-PseudoCache – Optionally use a real cache
    • DBIx-Class-Schema-Auth – Plan out remaining bits to get done
    • Net-Goodreads – Plan out remaining bits to get done
    • Data-Dumper-Concise – DwarnOnly
    • DBIx-Class – Logger Configuration
    • DBIx-Class – Logger Console Width
    • DBIx-Class – Non-Result based FilterColumn
    • DBIx-Class – Instance Based Relationship Helpers
    • DBIx-Class – Join Args
    • DBIx-Class – ResultSet Components
    • DBIx-Class-DeploymentHander – code cleanup
    • DBIx-Class-DeploymentHander – various doc patches
    • DBIx-Class-Helpers – Fix remove columns
    • DBIx-Class-Helpers – Work way to make SQLMaker helper
    • DBIx-Class-Helpers – ReadOnly
    • Log-Contextual – NullLogger ?
    • git-super-status – More Filters
    • git-super-status – More Sorts
    • git-super-status – Configurable Columns
    • git-super-status – Configurable Colors
    • git-super-fetch – get it started?
    • SQL-Translator – Finish SQL-Server cleanup
    • teatime – Convert 100% to REST
    • try-awesome – We have plenty exception generating frameworks, now we need a catching one
    • Log-Contextual-P6 – Port LC to P6
    • Log-Contextual-JS – Port LC to JS

    Pending Blog Posts

    • Event Loops are better than while(1)
    • Powerful benchmarking with Perl and ab
    • Commercial Cross Platform Git
    • Alternatives to Sub::Exporter
    • Cool things you can do with Sub::Exporter
    • Why Exceptions are here to Stay
    • The Problem with Exceptions
    • Refactoring dispatch tables into objects
    • Emacs vs Vim
    • Simple Perl Proxy for Productivity
    • Sweet Code, thanks to Moose and Catalyst
    • Keep track of failing tests
    • Revised OpenID post (or not)
    • Write Code to be Cargo Culted
    • The Toolsmith: Vim, zsh, IRSSI, XMonad, etc etc
    • Filtering out things
    • On Syntactic Arcana
  • 1 Comment
  • Filed under: Uncategorized
  • My Ideal workflow tool

    1. super fetch:

      • git fetch
      • git fetch –tags
      • git pull –ff-only (all local branches)
      • git reset –hard (specified branches)
    2. pull issues:

      • “rebase” issues from github
      • “rebase” issues from RT
      • “rebase” issues from JIRA
      • sync issues from remote repo
    3. super status:

      • Dirty?
      • Non-Tracking branches? How many?
      • Ahead tracking branches? How many commits total?
      • Unmerged branches?
      • Unreleased master? (no tag)
      • How many issues?

    My last post was about Distributed Issue Tracking. The above is why I’d be so interested in DIT. When I want to code I could sit down, run super fetch, run pull issues, and then run super status.

    super fetch

    super fetch is pretty simple and self explanatory, except for one part, the git pull –ff-only. It uses an idea I got while speaking with mjd. Basically, any branches that track a remote and can be fast-forwarded, should be.

    pull issues

    pull issues uses some as yet unknown tech that imports issues into a git reference (I’d say branch but really I’d rather it not be a head) as well as full, local issue tracking. The idea is that if I want to examine the issues of all of my repos, I don’t want to have to go to a website to see all of them.

    super status

    super status builds upon the ideas explored with genehack’s App::GitGot. Specifically, the status command. It lists some of the information above, and is still totally awesome, just not enough. Without colors, I think I’d format the output something like this:

    Optional the following would be prepended to the list:

    1
    2
    3
    4
    5
    6
    D      dirty?
    !TP    non-tracking branches
    !PC    total unpushed commits
    !MB    total unmerged branches
    !RC    unreleased commits
    I      issues
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    Repository Name                         D !TP !PC  !MB  !RC   I

    ACDRI                                   N   0   0    0    0   0
    Arduino                                 N   0   0    0    0   0
    Catalyst                                N   0   0    0    0   0
    Catalyst-View-CSS-Minifier-XS           N   0   0    0    0   0
    Catalyst-View-JavaScript-Minifier-XS    N   0   0    0    0   0
    Class-Accessor-Grouped                  N   0   0    0    0   0
    Config-ZOMG                             N   0   0    0    0   0
    DBIx-Class                              N   0   0   57    0   0
    DBIx-Class-Candy                        N   0   0    0    0   0
    DBIx-Class-DeploymentHandler            N   0   0    0    0   0

    Repository Name                         D !TP !PC  !MB  !RC   I

    DBIx-Class-Helpers                      Y   0   0    0    0   0
    DBIx-Class-Schema-Auth                  Y   0   0    0    0   0
    DBIx-Exceptions                         N   0   0    0    0   0
    Data-Dumper-Concise                     N   0   0    0    0   0
    Git-Conversion-Book                     N   0   0    0    0   0
    Git-Conversions                         N   0   0    0    0   0
    Harmony                                 N   0   3    0    0   0
    Log-Contextual                          N   0   0    0    0   0
    Log-Sprintf                             N   0   0    0    0   0
    Log-Structured                          N   0   0    0    0   0

    Repository Name                         D !TP !PC  !MB  !RC   I

    Lynx                                    N   0   0    0    0   0
    Lynx-SMS                                N   0   0    0    0   0
    Moo                                     N   0   0    0    0   0

    It would all be optionally color coded. Also, optionally the “good value” (usually zero) would be blank.

    In addition to the output above there will be increasing verbosities to actually list the things being counted etc.

    Anyway, I’m gonna start on the super status tonight, and I figured this would be a nice way to flesh out my thoughts. If anyone is interested in this let me know, I welcome feedback. I’ll probably implement it all in perl, as bash might be tough for something like this.

    Update: I got it mostly working!

    This takes a few commandline options and you can configure the defaults using git’s standard config tool. I probably need to consider the names of the switches and config, as well as write some doc, but it definitely works, which is very neat. Next I’ll probably want to add those verbosity flags, but really, I should deal with all those issues with my repos. I need to figure out how to suppress stuff I don’t care about too…

  • 2 Comments
  • Filed under: Uncategorized
  • Distributed Issue Tracking

    Ever since I heard about SD (Simple Defects) I’ve been enamored with the idea of distributed issue tracking. Unfortunately SD is mostly unmaintained, undocumented, slow, and has lots of deps. I could probably get over the latter two, but the first two are deal breakers.

    Fast forward eighteen months and I saw genehack’s App::GitGot. It’s a little sluggish (1.35s to merely list repos on my SSD) but it’s exciting because it can easily list my repos that are dirty or ahead by X commits. genehack is very receptive to changes, so this gave me an idea. First, what if we also listed how many unmerged brances there were? Next, what about unclosed issues? Obviously both of these ideas require some basic configuration, but it’s totally worth it.

    I figured that step one would be to make a minimalist bug tracker, storing the information in the current git repo. The idea being that if I have a git tracker I can easily keep track of what I have to do next, so I won’t forget what else to do. I’ve been working on it every day a little bit since YAPC and it’s been pretty fun! The only thing is that there are already a few other implementations of what I am doing. I might as well list and evaluate them now.

    git-issues

    First off, it’s implemented in Python, which is an immediate deal breaker, as I don’t have python installed everywhere I have git installed. On top of that it uses XML, which is not exactly easy to parse and modify. Finally it is basically dead, so it’s unlikely to get more features added in the future.

    ticgit

    Implemented in Ruby, which is a problem, just like with git-issues. It is extremely full featured, so if you are working on a Linux system all the time I’d say this is the route to go. Unfortunately it uses rubygems; unless something has significantly changed in the past couple years that means it’s gonna be a little sluggish for a CLI app.

    bugs everywhere

    Again this is a Python app. It seems very full featured like ticgit, so maybe it has the same benefits as ticgit. It seems like it has some really neat features, but I just don’t like the python dep.

    git-case

    This is implemented in bash, so it immediately jumped out at me as something that is going to work anywhere that I have git installed. Unfortunately it is unmaintained for about three years now. I emailed the author to see what’s up, so we’ll have to see what happens there.

    The Dilemma

    So my current dilemma is this: should I start afresh with a Perl app, possibly modelling after or even making it compatible with some of these other apps (be or ticgit) or should I pick up where bart left off with git-case? Before you jump to the former, realize that I don’t want to use any CPAN modules because I want this to be super simple to use anywhere one uses git; that is, all I should dep on is 5.8 and Git.pm (which is mostly useless.)

    Currently I’m leaning towards git-case, maybe with a name change as I probably want to make some backwards incompatible changes. Any ideas? Hopes? Dreams?

  • 2 Comments
  • Filed under: Uncategorized
  • FUD and Loathing in JavaScript

    A coworker sent this to our internal mailing list, partially to goad me into responding to the stupid comments. I don’t have an ars account, so I’ll just hope that trackbacks work.

    Here are the arguments that someone actually put effort into making:

    a) Magic ‘this’. This is this, except when this is that. JavaScript pushes you to use anonymous functions all over the place, except they always end up losing the proper context for the ‘this’ variable, so you end up having goofy code like “var _this = this” all over the place and then using that inside your callbacks or other functions. Some days I swear that the number of functions I manage to write that don’t use a renamed ‘this’ are actually smaller than the number that do.

    If you think it’s magic you clearly don’t understand it. That’s not really an argument. I agree that sometimes it’s confusing, but sometimes programming is hard. Sorry?

    b) 1 + “1″ – 1 = 10. Also, “1″ + 0 = “10″. Yes, this actually has caused bugs for our applications, where data that’s expected to be a number was loaded from a JSON file as a string due to a bug in another application, and the result was not good. All our loading code had to be updated to add a ton of type conversions all over the place. When I need something to be a number I really freaking absolutely want it to be a number, not a string or an object or null or anything else. Lua, which is very similar to JavaScript in most respects, fixed this problem by just not being retarded enough to use the same operator for addition and string concatenation.

    I agree, this sucks, but I hit it rarely enough that it doesn’t discount the language.

    c) Global by default variables. So even if you take the argument that dynamic typing is just “easier” because you don’t have to think about variable declarations, JavaScript throws that argument out the window by making you put ‘var’ in front of new identifiers all over the place. And then it silently screws you if you forget to.

    Again, I disagree with this, but maybe because we use Perl and Perl works the same way (with the advantage of use strict, which some JavaScript implementations recently added but doesn’t really handle that issue as far as I can tell.)

    d) Prototypes instead of classes. There are very few large-scale real-world JavaScript applications in existence that don’t plug in their own class system to work around the inherent uselessness of prototypes in large application architecture. Those same apps make minimal use of prototypes to extend the base JavaScript types, and only because JS was so poorly designed that even the two interesting built-in types it comes with are lacking half the features you’d expect them to have.

    Wow I can’t believe how much I disagree with this. Prototypes give you more flexibility, so sure, they have caveats, but I totally think it’s worth it. Like a lot of things, you need to exercise discipline when using them, but I can think of numerous times in our real world, medium sized app (14K lines of JavaScript) where it’s helped to have.

    e) Inability to create pass-by-value types. This is a frequent problem in just about every language aside from C++/D, actually. For those using JavaScript to write WebGL apps, take a look at all the linear algebra libraries for JavaScript. In 3D apps, you almost use vectors more often than you do scalars. Imagine if every integer in your app was passed by reference, so that “a = 1; b = a; b++” made both a and b equal to 2. Every little three component vector is a complete full object. They are passed by reference (the source of almost a half of the bugs in our WebGL game so far, in fact). They exist in great quantity, are heap-allocated, and are garbage-collected, which puts an intense amount of pressure on the GC which can and does result in GC pauses in even simple WebGL games, unless the developer jump through ridiculously complicated hoops to avoid creating new vectors in all the places where it’s logical to create new vectors. You can’t have operator overloading, so you have very large and ugly expressions to do basic operations. Accessing individual components is slow. The objects aren’t natively packed and hence are incredibly slow to push into a vertex buffer, unless you implement them as a Float32Array instances, which confuses the crap out of the optimizers of both V8 and SpiderMonkey currently. Did I mention they’re passed by reference?

    I can’t relate with this. I just have never needed to pass anything other than a scalar by value, and those are pass by value. I can see that it’s a real issue for games and whatnot though. Also realize this argues against the poster’s language of choice.

    f) No built-in include or require functionality. Seriously, still. Third-party libraries exist but almost all of them have some kind of bug or another, not least of which is a confusing caching problem in at least Chrome making doing actual development a pain in the butt.

    Using a third party library should be expected. JavaScript isn’t Python, it’s not made to be “batteries included.” If there are bugs in a library you use you should fix those bugs.

    g) Dynamic typing. Yes, I’m willing to start that argument. You start noticing it the most the second you stop writing little Web apps or Web pages and start writing large apps where you actually have data that persists for longer than a single mouse click or request/response cycle: add the wrong kind of object to an array to process later and get a crash later from a missing method or member in a completely different bit of code than where the actual mistake was. Fun times. Yes, Java makes static typing seem evil. No, Java/C#/C++ are not the one and only way to do static typing. Type inference, implicit interface binding, etc. give you all the “easy to deal with and not a lot of keystrokes” advantages of dynamic typing without all the bugs. The second most popular Web language — ActionScript 3 — is statically typed, in fact, despite otherwise being identical to JS/ECMAScript. As an aside, I get more crashes from the Python apps on my Fedora desktop than I do from the C/C++ apps (actually, none of the C/C++ apps on my desktop crash, now that I think about it). Missing member exceptions == so much easier to develop and maintain apps, right?

    I don’t think I’ve had a type issue in our “large [app] where [we] actually have data that persists for longer than a single mouse click” for longer than a typo.

    h) Speed. Yes, there has been some ridiculously immense amounts of effort by a large number of super bad-ass developers put into the language runtimes to make JS almost half as fast as a low-grade C compiler that a single college Junior could write in a few months. And LuaJIT is in the same boat as JS in terms of fundamental language limitations but manages to do better than every JavaScript implementation anyway. People who don’t understand what all the JS optimizations in V8 or such actually _do_ like to claim the JS can do amazing things speed-wise, but the reality is that all those optimizations are basically just “try very very hard to analyze the code to figure out types for variables and then compile it like a slightly retarded statically-typed language’s compiler would do it.” Oh, and there’s tracing, but then tracing also works on statically typed languages (and works better due to a lack of need for type guards in the generated machine code). Not a single one of those whizbang optimizations was invented by or for JS, in fact; most were taken from research JVMs (Java is evil!) or classical OOP languages (prototypes are awesome!).

    Nice! So the poster says: “JS is fast, but not as fast as C and the things that made it fast were taken from other VM’s so it doesn’t really count.” Ok Mr. C#, I’m sure you’re correct since C# is entirely original research :-) Also, is C# as fast as C?

    i) No IntelliSense even possible. Want to see what methods exist on that variable you’ve got there on line 187 of foo.js in your text editor? Too bad. Go trace through the code until you figure out where it was initialized, then go trace through the code to find out what its prototype has on it. And then hope there’s no code dynamically changing the prototype behind your back. In fact, just run it in a browser and set breakpoints, because finding out anything useful about the value any other way is basically impossible for any codebase larger than the toy_web_app.html sites that JavaScript apologists use to glorify the ease and simplicity of JavaScript. Some code editors try _really_ hard to do better, and almost kinda sorta succeed for the really simple cases, sometimes, once.

    Yeah, that’s a real thing I guess, but I’m not the target user of IntelliSense anyway.

    j) No advantage. JavaScript isn’t even special compared to other dynamically typed language. It is not capable of doing anything interesting at all all that can’t also be done by Lua, Python, Ruby, etc. None of the JS implementations are any faster than LuaJIT or PyPy or various other advanced JIT-ing implementations of other dynamic languages. JS has no plus sides to it compared to other commonly available languages. Oh, except it runs natively in a Web browser without a plugin. Which is the only reason in the world why it’s so popular. In fact, it’s the only reason it event _exists_. If someone 10 years ago had just thought, “heck, let’s drop an existing well-designed and well-established language into our browser and get the other guys to do the same instead of making everyone use this goofy little hackjob that NetScape came up with,” the Web would look a lot different (better) today. Just imagine the future if Chrome dropped Python into Chrome as a supported language. Or actually, imagine this: Google drops C/C++ into Chrome as a supported language (http://code.google.com/p/nativeclient/).

    The fact that it’s the most widely deployed VM in the world isn’t an advantage? The fact that there are three major VM’s leading to healthy competition and improvements isn’t an advantage? The fact that it’s in all browsers right now (unlike some crazy future where browsers need to implement C or (good lord!) C++ safely) isn’t a feature?

    Maybe I’m just a tool for thinking this guy just has confirmation bias. I’ve done the same thing of course in arguing against C#, so maybe I’m just as bad, but I can hardly take these arguments as reasons not to use JavaScript.

  • 6 Comments
  • Filed under: Uncategorized
  • Nicer git remote URLs

    Most open source git repositories that I interact with are hosted at git.shadowcat.co.uk. A few typical repo urls (read/write) hosted here looks like:

    1
    2
    3
    4
      dbsrgits@git.shadowcat.co.uk:DBIx-Class.git
      catagits@git.shadowcat.co.uk:Catalyst-Runtime.git
      p5sagit@git.shadowcat.co.uk:Devel-Declare.git
      gitmo@git.shadowcat.co.uk:Moose.git

    A handy trick is to make a file at ~/.ssh/config with the following in it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    host catagits
         user catagits
         hostname git.shadowcat.co.uk
         port 22
         identityfile ~/.ssh/id_dsa

    host dbsrgits
         user dbsrgits
         hostname git.shadowcat.co.uk
         port 22
         identityfile ~/.ssh/id_dsa

    host p5sagit
         user p5sagit
         hostname git.shadowcat.co.uk
         port 22
         identityfile ~/.ssh/id_dsa

    host gitmo
         user gitmo
         hostname git.shadowcat.co.uk
         port 22
         identityfile ~/.ssh/id_dsa

    Now that that’s done the repos before are simply:

    1
    2
    3
    4
      dbsrgits:DBIx-Class.git
      catagits:Catalyst-Runtime.git
      p5sagit:Devel-Declare.git
      gitmo:Moose.git

    I actually did that for my work and github stuff too, since I just don’t have the time to type those stupid domains all the time.

    Enjoy!

  • 1 Comment
  • Filed under: Uncategorized
  • Converting repos from Subversion to Git

    I have now converted something like 25 repositories from svn to git. I can fix undetected merges, correctly import tags, and clean up ugly (svk) commit messages.

    With this knowledge I hope to write a small, non-free eBook (7.50 USD I think.) But first I’d like a chance to convert your repository! The more repositories that I convert the more ground the ebook can cover. I’ve converted a number of repos for CPAN modules and I’d love to do more. My first thought was to convert the modules in the Catalyst repo, but sadly I’m not sure which ones I should do.

    So if you are interested in having your repo converted, I am totally willing to do it. All I need from you is an email, comment, ping, etc saying you are interested and I need to you be willing to check the converted repo to ensure that it’s good. I’ve gotten pretty good at this but I’m not perfect and I’m not taking the blame if you miss something :-)

    If you’d like to try your hand at doing this, I put all my conversion scripts online, so feel free to take a peak.

  • 1 Comment
  • Filed under: Uncategorized
  • New Stuff in DBIx::Class::DeploymentHandler

    I’m just releasing my first new release of DBIx::Class::DeploymentHandler in six months! For the most part the release is just a few doc tweaks, but it does have one important new feature, the “_any” version.

    If you didn’t already know, DBICDH has a handy little directory structure for how your deploys work. If you haven’t seen it, take a look. This new release allows you to use _any in place of a version or version set, which will run the given files no matter what version you are deploying to.

    Enjoy!

  • 0 Comments
  • Filed under: Uncategorized