tag:blogger.com,1999:blog-137624562024-03-07T21:06:37.228-05:00The reality of my fantasy lifeA rambling blog from Arron, a scrawny little dork who likes to code. ;)Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.comBlogger231125tag:blogger.com,1999:blog-13762456.post-66815754191257024322018-03-18T22:43:00.001-04:002018-03-18T22:43:23.064-04:00Runtime Error: Cannot find module 'foobar.d.ts' from TypescriptContinuing on with the theme of me using my illustrious blog as a dumping ground:<br />
<br />
This runtime error puzzled me. It compiled cleanly in Typescript, but at runtime raised an error. It shouldn't have even been compiled in the first place. So what's the deal?<br />
<br />
`Error: Cannot find module '../../../typings/foobar'`<br />
<br />
Well, the deal is pretty simple. The typing file contained an enum data structure. Since those get converted to actual code, that meant that the compiler emitted a 'require' statement for the type definition file, which meant that Node tried to load it... can't load a d.ts file at runtime, can you?Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-12478961105552009542018-02-07T14:20:00.002-05:002018-02-07T14:20:52.128-05:00"Something seriously went wrong: Invalid Parameter" for XPS 13 9360?I just had a simple Ubuntu update soft-brick an entire laptop. My less-than-two-years-old XPS 13 9360, to be exact.<br />
<br />
The error message was,<br />
<br />
<blockquote class="tr_bq">
Something seriously went wrong: Invalid Parameter<br />Shim was unable to measure state into TPM</blockquote>
<br />
Ironically I had spent the ten minutes earlier ranting to myself about how much I hated having to use macOS.<br />
<br />
Here's how I recovered the system.<br />
<br />
You'll need:<br />
<br />
<br />
<ol>
<li>A USB stick, formatted as FAT32</li>
</ol>
<div>
<br /></div>
<div>
Either <a href="http://www.dell.com/support/home/us/en/04/product-support/product/xps-13-9360-laptop/drivers" target="_blank">go here</a> or google "XPS 13 9360 bios update". </div>
<div>
<br /></div>
<div>
Scan the list of downloads for an entry that says "System BIOS" (you may have to click "View More" to see the entire list). Download it. The version I got was 2.4.2, but your mileage may vary. You'll only find an .exe file to download: that's fine. Take it and put it on your USB stick.</div>
<div>
<br /></div>
<div>
Plug the USB stick into the affected laptop. </div>
<div>
<br /></div>
<div>
Restart the laptop, and jam F12 as frantically as possible. Eventually you'll go into the bios boot menu. Uses the cursor keys to highlight the "Bios UPGRADE" entry, then press ENTER on your keyboard.</div>
<div>
<br /></div>
<div>
Click the "..." button on the next page, and then click the empty dropdown. You'll see entries like "F1, F2, F3", etc. Go through them all until you find the .exe you downloaded earlier. Select it, and press the open button near the bottom of the dialog.</div>
<div>
<br /></div>
<div>
Wait a second. If everything went correctly, the system will recognize the .exe file as a bios update. Press the "install" button, then sit back and relax. Maybe keep your animals away from the laptop, because this isn't something you'll want them to interrupt with their big stupid cat feet.</div>
<div>
<br /></div>
<div>
The computer will automatically reboot. If all went well, you'll be staring at your login screen again. If you sign in and are just staring at your default wallpaper, without a GUI in sight, do this:</div>
<div>
<br /></div>
<div>
<ol>
<li>CTRL+ALT+F2</li>
<li>Log in with your username (I hope you remember that), then type in the following commands minus the quotation marks</li>
<li>"sudo apt-get update"</li>
<li>"sudo apt-get upgrade" (this will not upgrade your distribution to Ubuntu x.x, it'll just grab whatever new updates there are for your current distribution. If all that sounded greek to you, don't worry about it.)</li>
<li>"sudo shutdown -r now"</li>
</ol>
<div>
Your computer should reboot after that last command. Now, when you log in, you should be staring at your old trusty desktop... I hope. If it's still broken, then I can't help you, but Dell probably can. Your service tag is under your laptop. Good luck, my friend.</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-70406485072642617672017-12-15T18:40:00.001-05:002017-12-15T18:40:44.053-05:00My 2017 Upwork experience in a nutshellDisclosure: haven't used account in a year because the site's been trending towards general uselessness and none of my existing clients were pleased and future clients simply wanted to avoid the site due to the rising expenses.<br />
<br />
> don't use site for a year because existing clients are pissed off at it, future clients are just like LOL no<br />
> get email in Q1 saying that my account is "needs" video call verification.<br />
> had billed over 300k in the 3-4 years i was super-active there, haven't used site since 2016, need to video chat for what exactly??<br />
> get three more emails like this, ignore them all<br />
> get a fourth and open it because i'm not paying attention to what i'm doing<br />
> inside is implication they "may" reverse the last payment transaction they made **over a year ago** if i don't comply<br />
> seriously think about letting them do it (the last transaction was a pittance) and making a fight out of it<br />
> too lazy, succumb to video call<br />
> suddenly dogs<br />
> holy shit dogs<br />
> person on other end must be working in the back office of a vet there's so many dogs barking<br />
> can't hear most of conversation<br />
> suddenly random programming question about a technology i haven't used in like 3 years<br />
> ??<br />
> give quasi-correct answer that i would have normally googled first for complete correctness.<br />
> call end<br />
> goodbye dogs<br />
> you were good dogs<br />
<br />
Upwork is so fucking weird.<br />
<br />
I do miss oDesk as a platform. They were pretty focused on connecting me with clients and then getting out of the way. Upwork is just trying to sell me membership plans and their bizarre interview currency and all this other random garbage that looks like its been pulled from the playbook of a mobile game.<br />
<br />
After taking a quick glance at the current marketplace, I get the feeling that whatever new-age fuckery Upwork has been up to has had a negative impact on solo high-level freelancers.<br />
<br />
Not sure I'd sign up for a new account in 2017, but your mileage may vary.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com1tag:blogger.com,1999:blog-13762456.post-44767033770840387652015-09-11T00:28:00.000-04:002015-09-12T04:40:12.528-04:00Hello, Typescript!After spending some time wrestling with it, a few months ago I began porting my Dart-based codebases to Typescript. I can't say the process has been particularly easy, but ultimately it's been worth it.<br />
<br />
<h3>
The tools</h3>
The roughest part of the migrations, I think, was dealing with the current JS ecosystem. In Dart, everything is pretty straightforward -- if you need a pub package, use `pub`. If you need to format your code, use `dartfmt`. Do you need to build for the web? `pub build`. If you're writing code for the server, it looks exactly like code for the client, except you switch out different libraries.<br />
<br />
While the ecosystem has finally consolidated around npm for packaging (sorry, bower), there's still some issues:<br />
<br />
<ul>
<li>If you're targeting the browser, should use webpack or browserify? It's a hard question to answer: they're _very_ similar, with the exception of a few things here or there.</li>
<li>If you're targeting io.js, do you use the built-in ES6 support, or do you go balls to the wall and use every ES6 feature _now_ and just compile down to ES5 with Babel?</li>
<li>Modules: CommonJS? SystemJS + JSPM?</li>
</ul>
<br />
There's no clear standout: it's more like you have two mediocre solutions to pick between, with only your gut instinct to go on. This is probably more an issue of maturity: in time, just like Grunt v. Gulp, an overwhelmingly better option will appear.<br />
<br />
<h3>
Typescript</h3>
<div>
Getting into Typescript isn't very straight-forward, either. For type definitions for external libraries, you're going to rely on DefinitelyTyped: a massive, massive repository that Github won't even display the entirety of online. In order to better finagle it, there is an npm module called `tsd` that installs a command line that will quickly find and download type definitions for you.</div>
<div>
<br /></div>
<div>
Then there's your `.tsconfig` file, which configures a TypeScript project, and has to be created by hand if you're not using atom-typescript (hint: use atom-typescript). </div>
<div>
<br /></div>
<div>
There's not a lot of documentation on typical Typescript applications.</div>
<div>
<br />
<ul>
<li>What directory _should_ your *.ts files go in? lib? src? scripts? I've seen them all.</li>
<li>Type definition files: do you check them into the repo? Yes? No? If no, how do you handle custom type definition files?</li>
<li>Should you check in the generated *.js files? They're build artifacts, but also required for the application to run after checkout.</li>
</ul>
</div>
<div>
<br /></div>
<div>
After those hurdles, though, things get a bit easier. Typescript, as a language, is great to work with; its obvious and its type syntax is very concise. It'll give you all of the ES6 features you hoped and dreamed for, as well as typing for analysis. On top of that, I think they're working on await/async support in 1.7.</div>
<div>
<br /></div>
<div>
I'll say this, though: I would have really appreciated comprehensive "Getting started with Typescript on io.js" and "Getting started on Typescript on the browser" guides. That's one of the things Dart does right: guides so you can hit the ground running right from the start.</div>
<div>
<br /></div>
<h3>
But Arron, [vague reason why I should still be using Dart]!</h3>
<div>
When I first started using Dart in 2013, it was pretty great. I didn't like the language all that much, felt too much like a random and wordy hodgepodge of other languages, but everything else about it was incredibly awesome...</div>
<div>
<br /></div>
<div>
...<i>in comparison to the state of 2013 web development.</i></div>
<div>
<i><br /></i></div>
<div>
Back then, Typescript was buggy, it was still Grunt vs Gulp, browserify wasn't stable yet (I think?), yadda yadda yadda, Polymer wasn't even born yet, and angular 1.x was still had a bunch of people trying to figure out the difference between a service and a factory and a provider.</div>
<div>
<br /></div>
<div>
So I deployed some production applications with Dart, and everything was good, for a while. Then these things happened:</div>
<div>
<br /></div>
<div>
1.) Clients started asking for features and integration with third party components.</div>
<div>
2.) Heavier usage, exposing the flaw of dart2js when it comes to tracking bugs.</div>
<div>
<br /></div>
<div>
#1 is the thing every bitches about the most when they start using Dart: awful javascript interop. Basically you write _tons_ of proxy objects to hide how ugly `dart:js` is, or you go raw and spend your time building against the `dart:js` library directly. Both are a massive timesink, and both are hideous.</div>
<div>
<br /></div>
<div>
Clients don't care about either of those. There's already a JavaScript version available, why can't you just drop in a file and go to work?</div>
<div>
<br /></div>
<div>
Why can't I, indeed.</div>
<div>
<br /></div>
<div>
#2 was a sucker-punch I didn't quite see coming. When you're building an application Dart, you normally use Dartium to run the code. Dartium has a DartVM embedded inside of it. The stacktraces are pretty clear when something goes wrong. There's also good IDE integration (Dart Editor at the time, WebStorm afterward).</div>
<div>
<br /></div>
<div>
But when you take a Dart application to production, it gets compiled down to minified JavaScript, and when it causes a stacktrace in a browser, the data that gets reported by your error tracking service is a nightmare to go through.</div>
<div>
<br /></div>
<div>
Here's an example from a Dart plugin for Atom (which is awesome, by the way): https://github.com/dart-atom/dartlang/issues/277</div>
<div>
<br /></div>
<div>
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSV52R6B8Z5fLg0XzgpdYFUoslmUGeVCRQ-i5ciGFYWYSBhSXqjQepRQNOjtIE0mzRQWcES1b6swq4F1B4Wrhgfq21UXAJuhSvsIHDraOI0ScBXLFKgVnUajSFCelg4q1skP_g5g/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> At /home/robert/.atom/packages/dartlang/web/entry.dart.js:15723
Uncaught Error: NullError: method not found: 'get$iterator' on null
Stack Trace:
TypeError: Cannot read property 'get$iterator' of null
at [object Object].J.get$iterator$ax (/home/robert/.atom/packages/dartlang/web/entry.dart.js:40600:41)
at OutlineView.dart.OutlineView._handleOutline$1 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:23413:23)
at [object Object]. (/home/robert/.atom/packages/dartlang/web/entry.dart.js:16917:32)
at _RootZone.dart._RootZone.runUnaryGuarded$2 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:30734:20)
at _BroadcastSubscription.dart._BufferingStreamSubscription._sendData$1 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:29878:20)
at _DelayedData.dart._DelayedData.perform$1 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:30072:18)
at _StreamImplEvents.dart._StreamImplEvents.handleNext$1 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:30145:16)
at _PendingEvents_schedule_closure.dart._PendingEvents_schedule_closure.call$0 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:30120:12)
at _AsyncCallbackEntry.dart._AsyncCallbackEntry.callback$0 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:29023:30)
at [object Object].dart._microtaskLoop (/home/robert/.atom/packages/dartlang/web/entry.dart.js:27728:12)
at [object Object].dart.wrapException (/home/robert/.atom/packages/dartlang/web/entry.dart.js:16669:17)
at _rootHandleUncaughtError_closure.dart._rootHandleUncaughtError_closure.call$0 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:30703:17)
at _AsyncCallbackEntry.dart._AsyncCallbackEntry.callback$0 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:29023:30)
at [object Object].dart._microtaskLoop (/home/robert/.atom/packages/dartlang/web/entry.dart.js:27728:12)
at [object Object].dart._microtaskLoopEntry (/home/robert/.atom/packages/dartlang/web/entry.dart.js:27734:11)
at TimerImpl_internalCallback0.dart.TimerImpl_internalCallback0.call$0 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:16100:35)
at invokeClosure_closure.dart.invokeClosure_closure.call$0 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:17775:41)
at _IsolateContext.dart._IsolateContext.eval$1 (/home/robert/.atom/packages/dartlang/web/entry.dart.js:15714:25)
at [object Object].dart._callInIsolate (/home/robert/.atom/packages/dartlang/web/entry.dart.js:15354:28)
at dart.invokeClosure (/home/robert/.atom/packages/dartlang/web/entry.dart.js:16817:18)
</code></pre>
</div>
<div>
<br />
The saving grace, in my production use of Dart, was that I had written all the code, so based on a stacktrace I could reasonably determine the general area that caused it. But imagine if I had a team of two or three developers alongside me?</div>
<div>
<br /></div>
<div>
Over time the advantages of using Dart dwindled. I'm not a dogmatic dude; I don't have any philosophical objections to Javascript, nor am I morally opposed to it because it's the spawn of Satan. </div>
<div>
<br /></div>
<div>
It's just an awkward language with an awkward ecosystem that's still growing up.</div>
<div>
<br /></div>
<div>
And, right now, when I compare Dart to Javascript / Typescript, I don't see as many compelling reasons to use Dart anymore. Really, the only things I'm missing from the language itself is a sane `this` semantic (yes yes, I know about function binding) and async/await, and the former is coming down the pipe via Typescript soon.</div>
<div>
<br /></div>
<div>
I still keep tabs on Dart, though. `dev_compiler` might be good for the community, and it seems like they're discussing pretty interesting language changes that might make Dart itself more palatable (dropping new, non nullable by default, RHS types).</div>
<div>
<br /></div>
<h3>
Lessons Learned</h3>
<div>
<br /></div>
<h4>
Being backed by a corporation doesn't mean jack when it comes to programming or programmers. </h4>
<div>
<br /></div>
<div>
A healthy ecosystem is created by producers. </div>
<div>
<br /></div>
<div>
An ecosystem of consumers is basically an impatient mob waiting for their corporate overlord to tell them what to do and how to do it, and by the way when will you be making the libraries for them to do it with?</div>
<div>
<br /></div>
<div>
Producers are the ones who make the cool shit that attracts consumers and other producers. They make Rails, Rack, Merb. Sometimes they're backed by a corporation, and sometimes they're just flying solo, but whatever the case, they're the ones that ultimately grow the ecosystem.</div>
<div>
<br /></div>
<div>
Dart doesn't have enough producers. There are a lot of promising pub packages that were abandoned early on after Dart went 1.0. I'm assuming Dart's familiar-to-a-fault syntax had something to do with that.</div>
<div>
<br /></div>
<h4>
Prepare yourself for the anger, for it will flow freely.</h4>
<div>
<br /></div>
<div>
I come from Ruby (C# before then, Java before that, C++ before that), and some things about ES5 still infuriate me.</div>
<div>
<br /></div>
<div>
No language is perfect. Learn to accept those flaws and mitigate them as best you can. And try not to think about the fact that setInterval accepts a function as its first parameter and not its last parameter.</div>
<div>
<br /></div>
<h4>
Learn about FRP, and use bacon.js to do it.</h4>
<div>
<br /></div>
<div>
<a href="https://baconjs.github.io/">https://baconjs.github.io/</a></div>
<div>
<br /></div>
<div>
FRP is awesome, and can simplify certain problems. I won't give you the salesman's pitch; check out the website and its examples, as well as tutorials, to get a better feel for how it might help you.</div>
<div>
<br /></div>
<div>
<br /></div>
<h4>
Language culture is almost as important as the language itself.</h4>
<div>
<br /></div>
<div>
I like <a href="http://kotlinlang.org/" target="_blank">Kotlin</a>. It is awesome. It has seamless interop with Java, while at the same time being incredibly concise and delightful to program in. </div>
<div>
<br /></div>
<div>
That doesn't change the fact that when you do interop with Java, you still have to deal with, you know, Java. Not the language's syntax, but the result of that: ugly and bloated paradigms. If you're not careful, it's like an overweight boxer punching you in the face every time you try to get any work done.</div>
<div>
<br /></div>
<div>
It's 2015, and Javascript has a culture of being extremely straight-forward with code and its documentation, and that's awesome. </div>
<div>
<br /></div>
<h3>
That's it.</h3>
<div>
<br /></div>
<div>
Sorry, felt like I needed another header just for the end. ¯\_(ツ)_/¯</div>
Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com1tag:blogger.com,1999:blog-13762456.post-6692835207730764182014-10-17T20:27:00.000-04:002014-10-17T20:27:24.957-04:00What OS powers my developer machine?Clients and friends know that for a long, long time I've used Linux as my primary development environment. There were a few years when I did .NET work, which required a Windows machine, but once I transitioned away from Microsoft's ecosystem it made no sense to work in an environment where your the cost of your developer tools and services start nearing the 4 digit range. (this was before BizSpark and DreamSpark or whatever Microsoft are calling their programs now a days).<br />
<br />I used to run Ubuntu back when it was on Gnome 2. When Unity came out, it was better than Gnome 2 by a long shot (anything was better than Gnome 2, honestly), but it was glitchy and annoying. Around that time I started dabbling with Gnome 3, and after a few weeks started running that hacked-up version of Gnome 3's "Gnome Shell" someone published to a PPA.<br />
<br />
It was a blast. While it had its fair share of bugs, it was mostly stable and the design kept things out of my way, unlike Unity's schizophrenic global menu and obtrusive dock. Of course, as Ubuntu progressed, Canonical decided to do things their own way, and support for Gnome 3 became poorer and poorer -- first it was default Gnome 3 apps that were missing, then Gnome Online Accounts was MIA, and then Gnome 3 was stuck at some ancient version full of paper-cut style annoyances.<br />
<br />
I think it was maybe a year ago or more when I decided to start clean with Fedora.<br />
<br />
And let me tell you, a clean Gnome 3 install is night and day than what is (probably) still shipping with Ubuntu. I had no idea how much I was missing until I started using Fedora. It's been a good year -- but it's been a really annoying few months recently.<br />
<br />
I can't remember where it started, but I had a need to download a program that offered a Linux version. So, fine, I'll just -- oh, it only offers a .deb. For Ubuntu.<br />
<br />
And that's how it started. A few days later (maybe a week), I was out fishing for another pretty polished application that offered Linux support... except not really: it only offered me a .deb.<br />
<br />
Now, I hate both rpms and debs. I'll take a binary .tar.gz any day of the week: I don't like giving random packages on the Internet sudo privileges. I've also seen what it takes to make an RPM and I'm not surprised that their first choice is going to be a deb file if they do any kind of package at all.<br />
<br />
Anyway, my point is that once I started leaving the "safety" of Fedora's repositories I discovered that in the "real world" Linux support is actually Ubuntu support and damn everyone else. You can probably download the sources and compile everything yourself -- I did that with Atom for a long time -- but it's still a pain in the ass. Atom, by the way, recently offered support for Linux -- sorry, Ubuntu.<br />
<br />
I don't want to run Ubuntu. I don't like Unity's interface. I don't want to deal with whatever frankenstein Gnome 3 they have going on. I am picky, and my days of fiddling with distributions is well behind me.<br />
<br />
Gnome 3(.12), by the way, still needs a lot of love. Over the year on Fedora, I've had the following random problems:<br />
<br />
* Computer seems to have frozen, but the monitors are off so I can't actually tell what happened. Can't wake the monitors up -- is the computer not outputting a video signal? Who knows.<br />
* The login widget on the lock-screen just... disappears after I click it. Nothing but a slate-gray oasis awaits.<br />
* Sometimes it freezes up. Sometimes. I'm not sure why. Or how.<br />
<br />
I don't know how to even begin to reproduce these things, or what logs I should look at, or if it even matters to anyone but me.<br />
<br />
Tonight, for the first time since I've had it (2+ years), my Macbook Pro froze. I held down the power button and restarted it. It told me that the computer had been restarted because there was a problem. It asked me if I wanted to start-up the programs I was running before the crash. I said OK. Everything was fine.<br />
<br />
It works. Homebrew exists. Applications that are multi-platform run on it without an asterisk. The performance is stable.<br />
<br />
I've been using it for my full-time dev work for about a month now. It's an experiment. So far I'm enjoying it.<br />
<br />
It's not really one thing that's driving me from Linux distros, but really a multitude of things. Openshot crashes, a lot. Pitivi... ... I'm not even sure the people who develop Pitivi use it. Why is Audacity showing me all these audio inputs when none of them have anything plugged in? Why is all this crossplatform software flowing in from Windows and OS X not really crossplatform? Why is pretty much every open source driver blacklisted in Chrome's WebGL implementation?<br />
<br />
There are things I find annoying about OS X -- it's shitty file manager is suspect #1 -- but everything else just works, and I'm OK with that. Hopefully in 3-5 years using RPM / Deb for applications will fall out of style, and a focus on usability will be present in the next generation of applications.<br />
<br />
I only got the Macbook Pro because a client had an environment with a L2PT / IPSEC VPN that could only be successfully logged in via Windows / OS X. The bug was documented on some unattended BugZilla installation somewhere years ago. Of course the earnings from the contract was vastly larger than the infuriating sum is cost me to buy the Macbook, so it was a no brainer, but the entire time I kept thinking "I could have bought 2 really good laptops for this price."<br />
<br />
I don't feel that way any longer.<br />
<br />
But no quad-core Mac Minis? Fuck off with that bullshit, Apple.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-66302169429013375692014-04-14T20:16:00.001-04:002014-04-14T20:20:53.057-04:00e2e testing with AngularDart.So this weekend I spent a grueling 12 hours trying to get an e2e test harness going for a personal project of mine I built in AngularDart.<br />
<br />
I will spare you the obscenity-laden recap and share with you the minimal amount of code needed to get an e2e testing solution going using NodeJS.<br />
<br />
Before you ask "why not Protractor?" let me explain: it doesn't work with AngularDart. I looked into the codebase and it relies on AngularJS's internals -- I had always assumed that AngularJS just emitted DOM events as the integration point for Protractor, but it turns out there's some private services in there like $browser that are accessed directly. Since I'm not using AngularJS, that immediately removes Protractor from the running.<br />
<br />
If you don't know what e2e is, it stands for end-to-end testing. Basically, you can unit test the hell out of your codebase, but at some point you have to make sure that based on user interaction everything works in harmony. It catches problems in your markup like not sending the right message when a user clicks an element, and other integration issues.<br />
<br />
I'm going to be sampling files straight from my repository, so the usual caveats apply: I am a foul-mouthed asshole and have no regrets about that, I might eat your baby, etc.<br />
<br />
1.) First off, let's get some necessary packages installed:<br />
<br />
<script src="https://gist.github.com/radicaled/10691491.js?file=package.json"></script>
<br />
<b>jasmine-node:</b> our test framework. This allows you to use Jasmine in Node, which is great, because Jasmine is great.<br />
<br />
<b>coffee-script:</b> CoffeeScript makes for very fluent, very readable test code. Your mileage my vary, but I use CoffeeScript where-ever I'd normally use JavaScript.<br />
<br />
<b>webdriverjs</b>: this is our API for interacting with Selenium. Despite the name, it is not the official Selenium WebDriverJS package; it is a more fluent, node-like API. It's got some minor issues: failures from Selenium don't bubble up, so you have to check the Selenium output to see what went wrong, and why.<br />
<br />
<b>selenium-standalone:</b> this package gets selenium server and has a helper executable that starts running the Selenium Standalone Server, which is required. It comes with Chrome driver.<br />
<br />
<b>gulp:</b> task runner. It's simple but undocumented; I will probably be migrating to Grunt in the near future. Dart has 'Hop' but that seems just as bare documentation-wise, and it's also more complicated to get going with.<br />
<br />
Running `npm install` (and optionally `npm install -g` so the executables packaged with those packages are available globally) gets us ready.<br />
<br />
2.) Now let's setup our Gulpfile. Typing 'jasmine-node spec/' gets pretty tiresome after awhile.<br />
<br />
<script src="https://gist.github.com/radicaled/10691491.js?file=Gulpfile.js"></script><br />
<script src="https://gist.github.com/radicaled/10691491.js?file=Gulpfile.coffee"></script><br />
<br />
Nothing too complicated, just some tasks to run tests. I prefer CoffeeScript, so Gulpfile.js just executes the CoffeeScript version of a Gulpfile.<br />
<br />
Just typing `gulp` in the terminal will start executing all of our specs. I keep my specs in the subdirectory 'spec/' instead of 'test/' because why not.<br />
<br />
Now, since this ended up being a total nightmare to get going -- I went through three or four more high-level APIs before I discovered what exactly was going wrong -- I ended up writing some "sanity checks." Here they are:<br />
<br />
<script src="https://gist.github.com/radicaled/10691491.js?file=jasmine_sanity_spec.coffee"></script><br />
<script src="https://gist.github.com/radicaled/10691491.js?file=webdriverjs_sanity_check.coffee"></script><br />
<br />
Typing 'gulp selenium' in one terminal, and then 'gulp' in another should result in 2 passing tests.<br />
<br />
Great! Now let's setup a basic config.coffee file to store our settings for an actual, but extremely simple, e2e test for our app. I'm not promising anything about the accuracy of the comments in this file.<br />
<br />
<script src="https://gist.github.com/radicaled/10691491.js?file=config.coffee"></script><br />
<br />
The timeout is super large because it takes `pub serve` forever and a day to compile an AngularDart application, and I'm still not sure if that has any influence on how long webdriverjs / Selenium waits until it tries to interact with a page.<br />
<br />
Now I wrote a small 'sanity check' test for the application itself, which basically ensured that the page loads properly:<br />
<br />
<script src="https://gist.github.com/radicaled/10691491.js?file=homepage_spec.coffee"></script><br />
<br />
This test just ensure that the page actually loads in the browser.<br />
<br />
You'll need to run `pub serve` first. The first time I ran this test it took about 60 seconds for dart2js to finish compiling on a Macbook Pro.<br />
<br />
<script src="https://gist.github.com/radicaled/10691491.js?file=project_import.coffee"></script><br />
<br />
Here is the test that gave me the most trouble: it's where I exercised the Selenium drivers beyond a simple sanity check and encountered the dozens of problems that had me pulling my hair out.<br />
<br />
Chrome wouldn't find any elements on the page, Safari worked fine (I discovered by accident) except that the webdriver won't interact with file inputs properly, Firefox crapped out with a bug in the shadow-dom polyfill, and PhantomJS was just... I don't know, there were too many errors with PhantomJS for me to even bother with.<br />
<br />
In the end, to get this test passing, I choose Firefox as the browser and commented out the shadow dom poly fill ("shadow_dim.min.js" in your AngularDart index.html file, probably), which caused some rendering errors but otherwise allowed the functional parts of the test to pass... but only in Firefox. I also removed some expected user behaviors and jumped straight to populating the file input.<br />
<br />
You'll notice I have some helper jQuery statements: normally in your stylish app, the file input is hidden. You trigger it when the user clicks on another element, like a button labeled "Upload File."<br />
<br />
However, you can't do that in Selenium. Since it's running a real browser, clicking on "Upload File" blocks the process since the OS then presents its file picker dialog. So what you have to do is use Selenium's API (webdriverjs calls this 'chooseFile'), which then simulates the process of attaching a file via a file input.<br />
<br />
Of course, since your stylish application has hidden the default ugly file input, there's nothing for Selenium to "click" on, so the `showInputs` makes the element visible for testing purposes.<br />
<br />
Is the `selectFile` script necessary? I don't know. It was there when I finally got everything working, and after 12 hours of hacking away trying to get a basic e2e test going it was 3AM and I wasn't about to try messing with it right then.<br />
<br />
Anyway, that's what I learned about e2e testing AngulartDart applications.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com1tag:blogger.com,1999:blog-13762456.post-85954196888926177612014-03-16T19:36:00.005-04:002014-03-16T19:36:55.884-04:00And the winner is...Recently, I evaluated some modern tools to build an SPA (single page application).<br />
<br />
The forerunners were Dart + AngularDart, or Dart + Polymer.dart.<br />
<br />
In the end, though, I actually went with AngularJS, which wasn't even on the original list.<br />
<br />
The major knocks against Dart + {AngularDart,Polymer.dart} was simply that they both enforced use ShadowDOM. Polymer had recently taken out "applyAuthorStyles" as well as the "lightdom" attribute, and AngularDart's templates are based on ShadowDOM.<br />
<br />
While that's fine for some hobbyist stuff I might do with Dart, I am definitely not interested in playing with ShadowDOM when I'm trying to quickly iterate an application. I don't have the resources to constantly reinvent components -- Bootstrap, for instance -- at every step of the process.<br />
<br />
I understand the uses of ShadowDOM, but they just don't apply to most of the work I do. I'm not building generic widgets for everyone to use across the web, I'm building them out specifically for a particular application. Maybe they're generic enough they can get slurped out -- fine. But at the time of me writing them, I'm interested in getting them working as quickly as possible.<br />
<br />
If I had a <b>dedicated</b> designer who would do all the work of crafting everything from scratch, I may have been more inclined to pick AngularDart... but then I would just be moving the burden to them instead. Either way it's still an unnecessary use of resources, especially in 2014, when you can cobble 50% of your webapp together with off the shelf components.<br />
<br />
I suppose I could have just used "regular" Dart and some additives, but I'd be pretty unproductive, and in the end I would have something that looks like a bastard child between Angular + whatever, with nothing to show for it other than a lot of wasted time[1].<br />
<br />
My days of reinventing the wheel were over years ago.<br />
<br />
All that said, AngularJS has turned out to be very nice! I originally started with plain old JavaScript, but recently transitioned to CoffeeScript; productivity has improved significantly and the code is much more readable.<br />
<br />
I've never had a problem with debugging the generated JavaScript in DevTools or Firebug, which is a complaint I hear alot about CoffeeScript. I suspect a really old versions of CoffeeScript produced some hard to read JavaScript, and that the meme still lives because, well, this is the Web and nothing really dies here.<br />
<br />
[1]: A project I once worked on was based off Sinatra instead of Rails because the team lead said it was "lighter." I looked at the codebase and it was basically a bastardized version of Rails: they pulled in most of the active* gems, and had half-assed "url_for" constructs that looked similar to their Rails counter-part but functioned completely different in certain ways. Developing against that codebase took forever. In some down time, I prototyped porting it to Rails proper, and it was about as fast as the Sinatra version...Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-47386848089723286402014-02-07T03:06:00.000-05:002014-02-07T03:06:17.602-05:00Dart: I'm probably doing it wrong......but it feels pretty good.<br />
<br />
<a href="https://github.com/radicaled/citadel/blob/0aa7f910151d75c57dbbdceb4a3a29d96b8f9ee8/lib/game/entities/src/animation_builder.dart" target="_blank">This file</a> exists purely so that I can write code like this:<br />
<br />
AnimationBuilder.on(entity)<br />
..animate('foo1', 1000)<br />
..animate('foo2', 1000);<br />
<br />
Instead of:<br />
<br />
new AnimationBuilder(entity)<br />
..animate('foo1', 1000)<br />
..animate('foo2', 1000)<br />
<br />
Or, without the 'DSL wrapper' entirely:<br />
<br />
var ani = new Animation();<br />
ani.animationSteps.add(new AnimationStep('foo1', 1000));<br />
ani.animationSteps.add(new AnimationStep('foo2', 1000));<br />
<br />
<br />
If I could have actually have a function called 'AnimationBuilder' that would call "new AnimationBuilder" under the hood, that would have been even better. The Nokogiri gem for Ruby does this: there's a class called Nokogiri and a function called Nokogiri. The function calls the class, so you can write code like "Nokogiri(xml_content).foo.bar" and just Get It Done.<br />
<br />
I am kind of a stickler for these aesthetics issues. I want my code to look good, because it's 2014 and programming is still text-based and I have to be the one staring at the result for 8 hours a day. It doesn't matter that there is literally no savings in terms of characters: the code reads more naturally with the 'DSL' so that's what I went with. That third block of code is simply not an option, but I included it anyway because I actually wrote it once before I recoiled and said "nope" and introduced AnimationBuilder.<br />
<br />
I'm probably dragging some of my Rubyisms into Dart, but I figure I'm an odd duck out anyway (everyone seems to be coming to Dart from C# or Java), so whatever.<br />
<br />
Gotta have fun, or why code at all?Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-22892838216373843802014-01-27T15:02:00.001-05:002014-01-30T16:05:04.954-05:00Half a year with Dart.So I've been fiddle-fucking around with Dart for about half a year now. I've used it for some internal stuff, and a small open source project.<br />
<br />
Pros:<br />
<br />
<b>Flexible problem solving</b>: Aside from executing arbitrary code at top-level and serious metaprogramming (both of which I sorely miss, coming from Ruby), Dart is a very flexible language. It embraces type inference, closures, top-level methods instead of one liner abstract classes. You're not going to find any amazing stuff like RSpec, Rake, or the Rails Router coming to Dart, though: the language is <i>simply not that flexible</i>. But if metaprogramming / DSLs / etc aren't your thing, Dart kinda lets you barrel through.<br />
<br />
<b>Structured ecosystem</b>: Dart has its own package manager, coding conventions, baked in "dartdoc" comments-as-documentation -- all the things you'd expect of a 2014 language. JS is still waffling: RequireJS or CommonJS or AMD? Bower for the client, npm for the server, and you sure as fuck aren't going to be using a single package from either source for both frontend and backend dev.<br />
<br />
<b>It's fast</b>: this and the clean syntax is ultimately why I chose it for a project over JavaScript. If the mythical ES6 or Harmony had shown up that day, I would have used that instead: decent performance, more flexibility, <i>and</i> a clean syntax would have won out over Dart's great performance and syntax.<br />
<br />
ES6 is Java's Project Lambda: it'll arrive several years late and JavaScript devs are going to have an aneurism when they see what the module syntax looks like.<br />
<br />
<b>Batteries included:</b> they packaged pretty much everything you need to get running quickly.<br />
<br />
Cons:<br />
<br />
<b>The library / parts syntax:</b> the way Dart handles including files in a library is <i>very</i> bizarre. The library declaration is straight-forward: `library foo;` in your library file. Simple right? You also have to specify that a file is part of a library, too; that's fine: `part of foo;`.<br />
<br />
Off to the races, right? Wrong. Because you have to go back to the library file again, and then add `part 'filename.dart'` as well. For every file in your project.<br />
<br />
<br />
<script src="https://gist.github.com/radicaled/72fa99bee30e5fcd203c.js"></script>
<br />
This is obviously for the compiler's benefit, because any human being wanting to know what file belongs to what project would just look at the source tree on the file system, like every other sane language on the planet.<br />
<br />
This is <b>flexibility without convenience</b>. You have <i>flexibility </i>in that you can, if having downed a six pack and are now in a drunken stupor, mix several different libraries and their implementation files in one directory and make out OK.<br />
<br />
But you don't have the <i>convenience</i> of declaring all files in a directory to be part of your library, even though that's what 99% of how everyone everywhere lays out their source tree.<br />
<br />
It's good to be flexible, but it's bad to be inconvenient.<br />
<br />
<b>Mirrors API</b>: Mirrors are analogous to C#'s reflections API and Java probably has something similar. There's not a lot of affordance in the API: using `dart:mirrors` means you are going to be writing a lot of code unless you are using it at its most base, simple level.<br />
<br />
<b>No generators: </b>Dart doesn't have generators, so <strike>List(...).where(...).map(...), is two iterations over a list; if your "where" returns every item in the list, you've done O(N) twice: once for the where, then once again for the map.</strike><br />
<strike><br /></strike>
<strike>For a language trying to be fast, this is a weird oversight since List is heavily used (and expected to be heavily used) in public APIs everywhere.</strike><br />
<b><br /></b>
<b>UPDATE:</b> Dart actually gets around this by using lazy iterables: where() returns a lazy iterable, and map() returns a lazy iterable based on the previous iterable. Thanks to +Lasse in the comments for pointing this out.<br />
<br />
<b>"The Editor Will Do It":</b> Dart relies heavily on using an editor of some kind. The Dart Editor is great for starting, but its weaknesses show when you move beyond 1-2 files for a project: there's no built-in keyboard-based navigation, no source control integration, no syntax highlighting support / integration for LESS or SASS or HAML or Slim or any of the popular templating languages -- <b>despite being built on the Eclipse platform.</b><br />
<b><br /></b>
A plugin exists for Eclipse, but it feels like a red-headed stepchild. I finally figured out how to import the files of an existing Dart project into my workspace by creating a "new" Dart project; when it asked me for the "project name" I just put the directory the existing files were located in, and walla, fooled the IDE I guess.<br />
<br />
I have a licensed copy for RubyMine, and thus can use the Dart plugin, but it needs serious love. It's obvious whoever is developing that plugin has never used it for anything other than ensuring the plugin <i>seems</i> to work.<br />
<br />
Maybe it's just me, but having to stop coding and mouse around clicking the '+'s and '-'s on a file picker to find the file I want consumes an inordinate amount of time and makes it hard to keep track of what I was doing. CTRL+SHIFT+R and done, son.<br />
<br />
In the end, Dart is still a respectable development choice. With ES6 being god knows where, doing god knows what, with god only knows how long until you can actually "use" it, Dart is a strong contender as long as you don't need that JS magic.<br />
<br />
But goddamn do I want to use a <a href="http://www.lighttable.com/" target="_blank">Light Table</a> supported language.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com5tag:blogger.com,1999:blog-13762456.post-39995536718297742332014-01-15T13:06:00.004-05:002014-01-15T13:06:54.131-05:00oDesk and eLanceI followed news of the <a href="http://allthingsd.com/20131218/odesk-and-elance-merge-to-create-one-big-freelancer-company-but-still-with-two-brands/" target="_blank">oDesk and eLance merger</a> with trepidation. So far, lots of "for nows" when it comes to whether oDesk will change.<br />
<br />
Personally, as long as they remain two separate business entities, I'm not concerned. The whole "client quality" kerfuffle everyone wants to keep starting is meaningless: there is nothing inherent to eLance OR oDesk that keeps crappy clients out. For all the flamey trollbaiting, I just checked my eLance account (I have an account on all the major freelancing sites), and I see your typical lunatics pitching insane projects for a pittance, same as oDesk:<br />
<br />
<blockquote class="tr_bq">
This post is for<b> software engineer that already completed successfully an exchange for bitcoin and other cryptocurrencies.</b></blockquote>
Anyone thinking that one freelancing platform is an asylum and the other isn't is drinking some serious kool-aid. The entire "client quality" issues stem from the self-serve nature of freelancing platforms in general: without another human to say, "Hey, this is crazy and way out of your budget" what you sometimes get are clients who are projecting their hopes and dreams instead of realistic job proposals. That will never change.<br />
<br />
All things being equal, ultimately platform preference comes down to usability and features.<br />
<br />
Personally, I use oDesk for the simple fee structure: you get paid, oDesk gets paid. No worry about membership levels and the restrictions based on membership level. That makes oDesk's focus laser-tight on connecting freelancers and clients, and for me that's a perfect combination.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-78387506343019478722013-12-29T20:24:00.000-05:002014-01-15T13:27:46.028-05:00Bitcoins and MMORPGs.I've been mulling over this question awhile now:<div>
<br />How do you make a free to play MMORPG that is not driven by a cash shop but is still sustainable as a business. In other words, how do you make a "clean" game in which no gameplay decisions are driven by the concept of microtransactions?</div>
<div>
<br />When gameplay decisions have to factor in the business side, the game inevitably suffers: see a million generic Korean grindfests where the only way to escape the monotony and get to the action is to pay for items. Very few games seem to escape this fate. The fewer players there are, the more expensive and disruptive items have to be in order to be profitable. The more players there are, the less items have to be disruptive -- the free to play community at large won't want to deal with players who "boosted" their way to the top but have no idea how to play the game.<br /><br />But what if you designed a system where every player paid to play your game, but invisibly, in the background, with no effort and cash required?</div>
<div>
<br /><b> Bitcoin</b>!</div>
<div>
<br /> It came to me a few hours ago as I was mulling over some game concepts. A minimalistic survival game, with no real UI to speak of, no macros or quest hubs. The game is its own user interface, similar to how Dead Space handled inventory management: every interaction you had with your inventory was part of the game. Nothing stopped, the world kept running as you fumbled through your equipment while the lights in the hallway ticked off one by one and the howl of monsters got closer and closer.<br /><br /> In a game like that, you can't have cash shops. Can you imagine walking up to an NPC vendor in the game, talking, then clicking through some immersion breaking dialogs to click through an immersion breaking gateway in order to buy some credits for $5 that will help you cut down trees faster, all because the tree-felling portion of the game was made more grindy to encourage players to buy something to cut down trees faster?<br /><br /> To me, it seemed like the only real option for sustaining a game like this was a subscription, which may as well make the game stillborn. The time of subscription-based games is over. WoW has sucked the air out of the room in that regard.<br /><br /> But I was browsing <a href="http://reddit.com/r/bitcoin">/r/bitcoin</a> earlier, not even sure how I got there, but just passing the time when it hit me:<br /><br /> What if your users mined bitcoins for you while they played the game?</div>
<div>
<br /> Their computers provide labor in exchange for being able to access and play your MMO*. In that sense, the concept of a subscription-based MMO* can survive through cryptocurrencies. You receive a currency (Bitcoin, Litecoin, even Dogecoin) while the user themselves put no tangible effort giving that currency to you. <br /><br /> It seems too perfect. For end-users, the entire thing is seamless: they turn on the game, they play, they turn it off. For you, you get paid when your players are playing. If you have a love of games, this is Heaven: the more fun you make your game, the more users you get, the more money you get. <b>You never have to compromise your vision of fun in order to make money, because a fun game that people like to play is metaphorically a "gold" (Bitcoin!) mine.</b></div>
<div>
<b><br /></b> It's a crazy thought, but it does make me wonder...</div>
Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-66718070224775516282013-04-03T17:21:00.001-04:002013-04-04T03:28:55.751-04:00JRuby on Heroku? Bah, humbug.My experiments with JRuby on Heroku have mostly been a bust.<br />
<br />
I migrated a fairly simple 2.0.0 application over to JRuby, which didn't involve much other than switching to Kramdown from RedCarpet 2, and spending some time fucking around with my `database.yml` so the `activerecord-jdbc-postgresql` gem would actually connect.<br />
<br />
But goddamn, the problems.<br />
<br />
I let the JRuby 1.7.3 version of the application run for a little less than 24 hours, and in that time I got:<br />
<br />
* about 6 hours of downtime spread sporadically throughout the period<br />
* four or five "memory quota exceeded" at peak time, which didn't seem to do anything<br />
* several random dyno crashes I wasn't seeing under Ruby 2.0.0, which were followed by...<br />
* ...many, many "boot timeout" errors, which I never saw under 2.0.0 unless I had a bad configuration / initializer that was causing the app to crash<br />
<br />
And those are just the critical errors. Performance across the board was crap: the New Relic comparisons from last week versus the switch to JRuby were pretty bad looking. Lots of request timeouts. <i>Lots of request timeouts. </i>And request throughput was apparently crap.<br />
<br />
That last thing -- throughput -- bothers me almost as much as the random crits above. The setup is running <a href="http://puma.io/">puma</a>, a threadsafe web server for Rack, so I was expecting to see much better request throughput than what I actually got. For those of you not in the know, JRuby has "real" threading, where-as Ruby MRI has a GIL and green threads, which means threading performance is not very good.<br />
<br />
Switching to JRuby should have given me a real boost in throughput, but, unexpectedly, performance was piss-poor and there was a significant increase of request timeouts. The site's not getting _that_ much traffic, and the assets are stored on Cloudfront, so...<br />
<br />
I don't have any idea what to make of this. Apparently the setup is working well for others (I don't see any complaints on Google, at least). But with such a simple setup on Heroku going sideways, I'm not sure what to make of it. Is it a bug in JRuby 1.7.3? A Heroku-specific problem?<br />
<br />
Meh. I've redeployed on MRI, and the numbers are turning back to normal.<br />
<br />
That concludes that experiment.<br />
<br />
<b>UPDATE 4/4/2013:</b><br />
<b><br /></b>
For curiosity's sake, I ended up chasing the source of the downtime to a bug in Kramdown not being able to deal with some erratically formatted content. The code doesn't throw an exception, it just... hangs, I guess. New Relic reports a ridiculously long runtime of 1.5 million milliseconds, but I'm not sure if that's because it actually takes that long to render, or something (probably Herkou) killed the process, and that's just how long it took. RedCarpet has no problems with the markdown in question, which explains why I wasn't seeing any problems before the switch to JRuby.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-54199449716362641932013-02-18T05:10:00.000-05:002013-02-18T05:10:11.730-05:00OS X 10.8 vs...<h2>
Fedora 18 / Gnome 3.6</h2>
Gnome 3.6 is very, very nice. It's not as refined as OS X yet, but you can see the Gnome team clearly closing the gap. The new lock screen is very nice and polished. Utilizing work-spaces is a snap. Gnome 3.6 has a very distinct, appealing style: once you open an application, there is little to no clutter. All you have is your app and the top bar showing you vital system information (battery life, wifi status, etc).<br />
<br />
The user interface is where the polish ends. As you'd expect if you've used any non-Ubuntu Linux distribution in the past few years, installing and updating applications is terrible. The built in method of installing applications from Fedora's repositories is awful; application packages (RPMs) you download from major vendors like Google (Google Chrome) have to be installed from the command line.<br />
<br />
It's unfortunate such a pleasant user experience like Gnome 3.6 attached to an unpleasant way of managing applications.<br />
<br />
<h2>
Ubuntu 12.10 / Unity</h2>
<div>
Unity feels like a kind of forgotten Frankenstein's monster. HUD, the system for quickly selecting items in an application's menu, only works sometimes. The global menu bar suffers the same schizophrenia, leaving you with an overall inconsistent experience. When they work, they work beautifully. When they don't... well, meh.<br />
<br />
The dash is nice and responsive, but often the search results hit the barn wall. Dash draws in search results from websites like Amazon.com, cluttering search results with unrelated items: searching for "photo" brings up <i>Shotwell Photo Manager</i>, as well as <i>Birds of Prey</i>, <i>Kindle Fire HD</i>, and what literally looks like a pornographic video. ... okay, no, it's apparently a smutty adult novel with a risque' cover. Still, not exactly what I was looking for, and definitely not what I want anyone to see if they're looking over my shoulder.<br />
<br />
Installing applications is nice and straight-forward: the Ubuntu Software Center is a little sluggish, but search results are easy to browse. Installing applications from the Internet -- Google Chrome, Scrivener for Linux -- is straight-forward and very painless.<br />
<br />
Unity needs a lot of shine, but seems promising.<br />
<h2>
Errata</h2>
Some things I really like about OS X that have no Unity / Gnome 3.6 parallel.<br />
<br />
* The Command button. I didn't understand how great this single button was until I started using it. Mac's have the standard Alt and Ctrl buttons, but the Command button is the primary modifier for interacting with applications. Command C always copies, Command V always pastes. Command W always closes a window, and Command T always creates a new tab. And because these keystrokes are divorced from the Ctrl key, you can actually copy and paste inside of a terminal window exactly the same as you'd copy and paste from a GUI application. The uniformity is great.<br />
<br />
* Built-in gestures. You can summon application window overviews with a simple swipe, move between windows, open the notification panel, pinch and zoom... gestures don't feel like a tacked on feature. If Unity or Gnome 3 have a similar feature, they're hard to discover. OS X told me straight up during the setup procedure how to use the mulit-touch gestures.<br />
<br />
* Coherent animations. When you download a file from Safari, the file's icon goes flying into the "downloads stack." When you minimize an application, you watch it disappear to its place on the dock. There's never any question of where a window went or a button just did. Most things in OS X have a nice, smooth animation that visually elaborates. It's thoughtful.<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-32592962208732351532013-02-05T01:21:00.002-05:002013-02-05T01:21:31.932-05:00Ruby: Ensure blocks can alter flow control!This one bit me -- I've only found it documented in one place, <a href="http://blog.leshill.org/blog/2009/11/17/ensure-with-explicit-return.html">here</a>, but I also discovered the behavior after debugging a strange problem I was having with some command line processes not exiting properly when they received the exit command.<br />
<br />
Basically, if you exit from an ensure block with "return" it behaves the same as if you had done a "rescue Exception" statement, which means it swallows up all exceptions, including exceptions raised to terminate the Ruby process when it receives SIGTERM, SIGQUIT, SIGINT, etc.<br />
<br />Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-41580045202056953252012-09-16T07:14:00.001-04:002013-01-17T14:58:23.798-05:00FTL isn't a Roguelike -- or if it is, its a very bad one.<a href="http://www.ftlgame.com/">FTL</a> was just released this week -- it's the space ship management game where you cut a swathe of destruction across the galaxy because something bigger and badder than you is doing just the same, nipping on your heels the entire time.<br />
<br />
The game is pretty simple: you got crew inside your tiny tin-can cruising the galaxy. You got weapons, you got shields. You got systems the enemy can target on your ship to disable your shields, life support, steering, and you can do the same thing to them.<br />
<br />
It sounds like fun, and it is, for awhile.<br />
<br />
It purports itself to be a roguelike though, and that just ain't so. It is entirely <i>too random</i> to be a roguelike. In a roguelike, when you die, there's that moment where you go, "<i>Why did I do that?</i>"<br />
<br />
You ask yourself "<i>why did I do that?</i>" because you understand that your character's death was totally avoidable. You could have checked the room you just entered more thoroughly. Maybe you were distracted and were just mashing one of the direction buttons, and your character walked over a trap or fell into a barely noticeable crevice to his doom. You could have totally looked at the frost giant in that next room (the one that killed you with one shot), decided you weren't ready, then turned around and went looking for better equipment, or a way around. Or maybe you just <i>had</i> to drink that unidentified potion because you are a freakin' lush and can't stop rolling the dice with your intestines on the line. In a roguelike, death sucks, but you did it to yourself, so while it is annoying, it rarely becomes too frustrating, because "<i>how can I avoid that next time?</i>" immediately follows. That's where some of the fun is.<br />
<br />
FTL is the exact opposite of that. The game can and will literally set you up to fail; it is unavoidable and incredibly unfun. I'll go as far as to say that the game is more frustrating than fun once the charm wears off -- there is nothing like canting your head to side, staring at the screen and muttering "wtf?" because in the second sector you ran across an enemy that has 3 shields -- and you only have enough weapons power to fire 3 laser shots at a time. The game is structured in a way that you are either lucky or you are not. If you are lucky, you will come across some weak enemies, get some missiles and "drone" weaponry early on. If you are unlucky, you will barely scrape along, if you survive at all.<br />
<br />
And barely scraping along is meaningless, as I found out the first time I made it the boss.<br />
<br />
The boss had four shields, a laser cannon, a beam cannon, and something that fired at least 3 missiles every volley. I had four lasers shots a volley, an empty missile launcher, and a beam weapon that doesn't work if shields are up.<br />
<br />
Despite the enemy ship being the size of a small planet, if I missed even /one/ laser shot, it would be impossible for me to damage the boss ship at all -- in FTL shields regenerate a few seconds after they've been depleted, leaving you with a very narrow opening. So in one volley you absolutely need to knock down all four shields with all four shots, or else you'll have to wait another 15 seconds to try again. If you miss one its a meaningless gesture; you can't damage the hull, so you can't destroy the ship.<br />
<br />
So of course that's what happened: the game, having decided I would fail early on, let me struggle through to this last moment, where it put me in front of an enemy I had no way of beating.<br />
<br />
You can only visit a handful of planets in a sector before the enemy armada starts blocking off the left side of the map, encroaching ever closer to your current position., You don't have the choice of sticking around and trying to scrap together as much "scrap" as you can get to afford new weaponry and crew members; you are either lucky, and on the journey to the sector's exit you got some easy scrap and nice weapons, or you are unlucky, in which case you will be unable to achieve victory.<br />
<br />
Once I realized how the core of the game worked, I would be a few sectors in, less than halfway to the final showdown, and I'd look at the state of my ship and go "I'm not going to make it to the end." It's a realization that sucks the life out of the game, because there's nothing you can do to correct your course. You're screwed.<br />
<br />
For a $9 game, I guess it was worth the 6 or so hours I got out of it, though.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com3tag:blogger.com,1999:blog-13762456.post-81492864459694953852012-09-08T06:12:00.000-04:002012-09-08T06:12:28.194-04:00Boobytrap your Monkey Patches!If you are going to override an entire method with a monkey patch, at least do this:<br />
<div>
<br /></div>
<pre>raise "Make sure I'm still required!" unless Gem.loaded_specs["GEM_NAME"].version.to_s == "VERSION_THAT_REQUIRED_PATCH"</pre>
<div>
<br /></div>
<div>
somewhere inside the file that does the monkey patching. Consider it a courtesy for everyone else, including yourself.</div>
<div>
<br /></div>
<div>
...</div>
<div>
<br /></div>
<div>
Okay, so I spent about 7 hours fiddle-fucking around with an inexplicable circumstance that came down to someone monkey patching an entire goddamn class by copying and pasting the Git HEAD version of that class so that an older version of the gem could use some of the newer version's functionality. Of course, 10 months later the underlying gem got upgraded way past the version the monkey patch came from, so a whole subset of functionality just broke "like magic!"</div>
Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-40948097579663438872012-09-08T03:00:00.000-04:002012-09-08T03:02:06.775-04:00Devise: Logging in a user from a custom controller.<h4>
<i>"Devise is a nightmare I have suffered only for the shining jewel called Omniauth clutched jealously within its thorny tentacles." -- a wild Arron under the influence of several frappucinos.</i></h4>
<br />
If you want to log in a user from a custom controller in Omniauth, this is your only hope:<br />
<br />
<pre>user_params = params[:user] || {}
user = User.find_by_username(user_params[:username]) || User.find_by_email(user_params[:email])
if user && user.valid_password?(user_params[:password])
sign_in :user, user
else
# destroy the world.
end
</pre>
<br />
You're probably thinking, "Can't I use warden.authenticate and cut down on the code and not have to do that nasty || at the beginning?"<br />
<br />
No. <a href="http://stackoverflow.com/questions/6143814/devise-have-multiple-controllers-handle-user-sessions">See this question on StackOverflow for an explanation</a>, but the short version is Devise doesn't want you to be able to use warden.authenticate anywhere outside of Devise::SessionController derived classes. Hilariously, if you go trolling for information on warden.authenticate you will find mostly unreplied to threads in Devise's Google Group, which is too many capitalized words in a row. If Google is a verb, can I refer to its products in lower case as well?<br />
<br />
Goddamn. Does anyone remember Authlogic?<br />
<br />
User#authenticate anywhere you wanted and you were fucking <i>done, son.</i> Yeah, Authlogic doesn't (or didn't) come with pre-built views like Clearance or Devise, which probably had a hand in it falling out of favor, but still, it was simple and almost impossible to screw up.<br />
<i><br /></i>
Theoretically you can get Omniauth up and running with anything, really, including Authlogic, but realistically setting up Facebook / Twitter login with Devise + Omniauth takes only seconds, and by the time you are screaming obscenities at your IDE it's too late to use anything else, assuming you even could -- I'm seeing that a lot of nifty stuff like rails_admin uses Devise under the hood.<br />
<br />
Still hate the shit out of Devise for custom stuff, though.<br />
<br />
That's right, <i style="font-weight: bold;">hate.</i> I am a mean coder. Rawr. Rawr!<br />
<br />
Get out of here. Shoo.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-85814404918507071612012-07-29T18:04:00.003-04:002012-07-29T18:04:31.440-04:00The Tablet Interface is coming to a PC near you: Thank God!I absolutely cannot wait until tablet interfaces come to every operating system. I just spent the last 2 hours watching my mom fumble through Windows 7 shitty interface as I taught her how to copy files from "My Pictures" to "Dropbox."<br />
<br />
I'm not even going to go into the whole "oh fuck, which cloud service do I tell her to use so she can easily back up her important photos" conversation I had in my head for like 10 minutes before that. On the desktop, all experiences are equally shitty; it ultimately came down to a matter of, "which service provided least friction."<br />
<br />
It was Dropbox, of course; they ask for your name, an email address, and a password and then you're off to the races. She could manage that part on her own. Navigating through the files was a total pain, though, and I realized just how idiotic file manager interfaces are for regular every day computing. I mean, I'm a programmer, so I'm used to stuff being designed-by-stupid, but watching someone else struggle with these kinds of basic computing tasks is eye-opening.<br />
<br />
The experience with Android + Dropbox is much easier. Smooth, intuitive for even someone who has no idea what they're doing.<br />
<br />
Right then I realized that despite all the bitching about tablet interfaces, they do the Unix philosophy just right.<br />
<br />
Each app does one thing, but each app does that one thing very, very well.<br />
<br />
The Dropbox app? It lets you view and upload your Dropbox files. In a few clicks any file you want is uploaded or downloaded. It's that easy.<br />
<br />
And, much like Unix pipes, integration is everywhere: anything that uses the standard "share" mechanism on Android can send a file to Dropbox. And Dropbox can send those files back using the "share" mechanism.<br />
<br />
Tablet / Mobile interfaces like Android 4.0 are probably the best thing to happen in computing since... I don't know. All time?<br />
<br />
I cannot wait until tablet interfaces come to PCs. Most of the savvy dudes and dudettes are going to turn them off because we need to get at the technical shit, but for everyone else? Kiss going over to your neighbors to show them how to send a file to their friend goodbye.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com2tag:blogger.com,1999:blog-13762456.post-61719921277152242522012-05-25T17:18:00.000-04:002012-05-25T17:18:19.975-04:00KittyCaptcha works!So, I've got a site I've got some problems keeping spam out of. I integrated with Akismet, which hits the barn wall as far as this site is concerned, and I also do a little bit of heuristics, based on poster location, amount of links / keywords in a particular piece of content, etc.
<br />
<br />
Akismet catches a lot of valid content as spam, so every few days I go through the spam bucket via the admin console and blindly white-list anything that doesn't look like spam. That was working OK for awhile.
<br />
<br />
Anyway, a few days ago I look and see that there are 163 identical bits of content, all of which completely skirted Akismet. Genius. It was obviously a bot. Now, part of this problem was that I had previously removed reCaptcha a few days ago as usability wise its terrible, and I actually failed a few of the reCaptcha tests myself because the scrambled words it presents are almost impossible to read these days.
<br />
<br />
So I figure, "Akismet will catch most everything, why use a captcha?"
<br />
<br />
As it turns out Akismet seems to catch very little, even when I'm marking items as spam. Even when things are *obviously* spam -- several dozen links, incredibly high keyword density -- it just completely misses the mark.
<br />
<br />
I rack my brain.
<br />
<br />
HashCash? No good implementation details, plus the concept hasn't been proved yet anywhere.
<br />
Simple math captchas? I hate math.
<br />
<br />
Then I remember way back when. A few years ago, people were talking about Microsoft Research's Assira and some random dude's KittenAuth. Neither caught on: Assira has good image breadth but looks like crap, and KittenAuth isn't very detailed regarding its implementation. Back then I initially dismissed it as a fruitless endeavor: where would you even get a large assortment of kitten pictures from? You'd have to partner with someone like Microsoft or come up with your own small batch of images that would quickly be "solved" by a human being paid 10 cents an hour.
<br />
<br />
But that was a long time ago. Now we've got Flickr, Instagram, Google Image Search. I have all the Internet's random kitten pictures at my disposal. I just need to use them to their fullest, cutest effect.
<br />
<br />
So I dig around, study some techniques on form signing with encryption, how to avoid replay attacks -- cracking the captcha once, by hand, then using it to resubmit over and over and over again ... -- and about 2 hours later I have a simple but adorable KittyCaptcha.
<br />
<br />
I deployed it into production last night, and haven't had a single drop of automated spam almost 24 hours later. Regular content is flowing through quite nicely.<br />
<br />
This was a pretty poorly written post, I realize, but it's mostly stream of consciousness and I can't be bothered to go back and edit anything.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-85012780540035108362011-10-28T23:54:00.003-04:002011-10-29T00:01:08.974-04:00accepts_nested_attributes_for, belongs_to, and has_many#buildThere's a self-explainatory code sample before.<br /><br />Basically, if you have accepts_nested_attributes_for on a belongs_to relation, you can't use model.has_many_relationship.build params[:has_many_relationship] -- Rails bugs out.<br /><br />This is because, AFAIK, model.has_many_relationship.build params[:has_many_relationship]<br /><br />assigns params[:has_many_relationship] first, BEFORE assigning the foreign keys that link the relationship with the model.<br /><br />Code:<br /><br /><pre><br />class User < ActiveRecord::Base<br /> has_many :papers<br />end<br /><br />class Paper < ActiveRecord::Base<br /> belongs_to :user<br /> accepts_nested_attributes_for :user<br />end<br /></pre><br /><br /><pre><br />class PagesController<br /> def create<br /> # The below line FAILS;<br /> # current_user.papers.build params[:paper]<br /> paper = current_user.papers.build<br /> paper.attribute<br /> end<br />end<br /></pre><br /><br />"current_user.papers.build params[:paper]" does this under the hood:<br /><pre><br /># this triggers accepts_nested_attributes_for, when user_id is currently blank, so it will fail.<br />Paper.new params[:paper] <br />Paper.user_id = current_user.id # too little, too late!<br /></pre>Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-2372120251036242282011-08-10T22:40:00.002-04:002011-08-10T23:07:27.545-04:00"What do you think of Cloud9 IDE?"I think it'll fail.<div>
<br /></div><div><a href="http://cloud9ide.com">Cloud9 IDE</a> is bills itself as "development-as-a-service", but it's really just a web-based editor with some built-in support for running Node.js applications. Don't get me wrong, it's a really good web-based editor, but alone isn't going to cut it.</div><div>
<br /></div><div>I mean, sure, you can run Node.js... but what about Ruby? Python? PHP? Yeah, you can edit the files, but what good is that without being able to test those changes? Deploy them to a staging server? Production? Run your project's test suites?</div><div>
<br /></div><div>Frankly, I think they're got the right idea but the wrong product.</div><div>
<br /></div><div>I think they should be selling a "Cloud9 DE" -- <i>a cloud-based development environment</i>. </div><div>
<br /></div><div>Let me tell you a story about an old, old Rails project I worked on. It was a popular site -- had millions of visitors a month -- but it was built using the 0.x series of Rails. Old as dirt. Development on it had started way before we got sweet things like Bundler, a more robust Rubygems, etc. And that was reflected in the codebase and some of the <i>hand-written</i> C libraries we had to use to hook into system libraries, etc.</div><div>
<br /></div><div>In fact...</div><div>
<br /></div><div>It was so damn old and brittle that we couldn't get a local copy running, for any of the developers. Instead, what Our Glorious Leader decided was that he would make copies of the actual production instance running on EC2, scrub the database, and then spin up an EC2 instance with these modified images for each developer.</div><div>
<br /></div><div>We worked through SSH, mainly using Vim or Nano, but I actually got some "SSH filesystem" deal going on Ubuntu (can't remember, FUSE?) and could edit my files using Gedit and etc.</div><div>
<br /></div><div>It was awful, fucking awful, let me tell you. A completely miserable experience. But if the code weren't such shit, and the concept had been fleshed out just a little more...</div><div>
<br /></div><div>So, interlude over, and back to the topic at hand: Cloud9 IDE is the right idea, wrong product.</div><div>
<br /></div><div>I think they should be selling <i>remote development environments</i> -- prepackaged Amazon EC2 images, spun up and down on demand, billed by the minute and ready to go for whenever you need to start hacking.</div><div>
<br /></div><div>One click should get me a prepackaged EC2 instance ready for the latest Ruby on Rails development, and one more should get me a public (or private) Git repo checked out and ready for development on that EC2 instance.</div><div>
<br /></div><div>You'll always get a clean system for every project. Don't run MySQL/etc in the background if this project doesn't need it.</div><div>
<br /></div><div>You'll always have SSH access, so if you need to do some tooling around in that project's instance, no problem. Need to run tests, or some other custom shell command? No problem.</div><div>
<br /></div><div>You'll always have access to your development machine, no matter where you are, via the Cloud9 IDE itself. Don't like the interface? Mount the filesystem using FUSE and hack the code with your favorite IDE.</div><div>
<br /></div><div>Taking it one step further, let teams create their own prepackaged developer images so that getting a new developer set up is as simple as adding him to a team in the Cloud9 IDE. Now you're suddenly measuring developer set up time in <i>minutes</i>.</div><div>
<br /></div><div>That's valuable. That's worth money.</div><div>
<br /></div><div>A web-based editor for $14.99/mo? No.</div><div>
<br /></div><div>Remote development environments like the one above ~$60/mo? Hell yes.</div>Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com3tag:blogger.com,1999:blog-13762456.post-30954963856207102802011-05-26T00:33:00.003-04:002011-05-26T00:35:35.593-04:00oDesk WTFsApplicants that:<div><ul><li>Apply to a job, but state very clearly when asked that they have no experience in the relevant technology and have no intention of learning the required technology</li><li>Apply to a job, but state that they have no intention of finishing the project within the alloted budget</li><li>Apply to a job, beg for a chance, then completely ignore instructions and try to sell you some half-baked CMS they had developed for another client</li></ul></div>Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com1tag:blogger.com,1999:blog-13762456.post-69196251249027116842011-05-15T21:25:00.004-04:002011-05-15T21:34:22.609-04:00Ubuntu v. FedoraWTF.<div><br /></div><div>So many bugs in Ubuntu 11.04, all of them with Unity. </div><div><br /></div><div><ul><li>Crazy graphical errors that make it impossible to work (I mean that literally), </li><li>Unity steals title bars at random so I can't can't drag some title bars for dialogs or windows,</li><li>the global menu steals some (SOME) of the menu bars in Eclipse, but not others, leaving me in a fucked up wasteland of not being able to access functionality without knowing the keyboard shortcut,</li><li>Unity decides that no, it does not need to hide at the moment, and there's nothing you can do about it, so the leftmost 50ish pixels of my applications are completely inaccessible,</li></ul><div>All this shit for a dock that doesn't do anything yet.</div></div><div><br /></div><div>Fedora 15 works like a dream on my laptop, no weird errors or anything like what Unity's been boning me with. I'm looking into exactly what it would take to migrate my development machines from Ubuntu 11.04 to Fedora 15.</div><div><br /></div><div>The only alternative is to wait 6 months and *hope* Unity stops being so goddamn buggy. I want to like it, but Unity seems less like a product and more of a promise of what could be.</div>Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-56860538936436018162011-04-30T02:37:00.002-04:002011-04-30T02:42:39.673-04:00UJS drivers (rails.js / jquery-ujs.js) -- load them LAST.Don't load your UJS driver (rails.js or jquery-ujs.js) before your application logic JavaScript.<br /><div><br /></div><div><script src="https://gist.github.com/949480.js"> </script></div><div><br /></div><div><br /></div><div>Why? Because your UJS driver is going to hook into the submission events for ajax elements. If you need to run a validation (or anything like it) that has to be executed BEFORE form submission occurs, because it may cancel the submission event, you need to have that code hook into the submission events before your UJS driver does.</div><div><br /></div><div>Therefore, load your UJS driver last.</div><div><br /></div>Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com0tag:blogger.com,1999:blog-13762456.post-39032175852190430492011-04-08T16:53:00.003-04:002011-04-08T17:07:24.037-04:00Mint.com is pretty awful now.Mint sucks. What happened? After Intuit bought them, they added support for one of my previously unlisted banks, but then almost immediately all four Bank of America accounts I had inputted stopped updating.<br /><br />And just awhile ago, my Prosper account stopped updating.<br /><br />So now I have:<br /><br />* a PayPal account I get non-stop "low balance" warnings for, even though the balance hasn't changed in over a year,<br />* a car note account that doesn't show my remaining balance,<br />* An Ally CD,<br />* and one bank account.<br /><br /><br />The most hilarious moment of this has to be that today I got an email from Mint, claiming that they've improved their back-end so now they don't talk to a 3rd party any more to get your bank updates: they connect directly to the financial institutions instead. Too bad connecting directly with the banks is apparently less robust than connecting through that 3rd party, am-i-rite?<br /><br />Runner up for most hilarious moment: Mint claims that you have to turn off all (ALL) of Bank of America's three-factor security mechanisms in order for Mint to work, because they're "unsupported." I have an account with another bank that updates perfectly fine via Mint, and it uses the same three-factor security that Bank of America does.<br /><br />It's unfortunate that Wesabe and the rest of them died off so quickly; they probably could have used this moment to start picking up customers as they drop off of Mint.<br /><br />There is no way I'm turning off any bank's additional security. I've already had my identity thiefed twice (caught by the bank both times before they did any real damage), I am not making it easier for someone to ninja my bank account, because, you know, there is <i>MONEY IN THEM THERE ACCOUNTS</i>.Anonymoushttp://www.blogger.com/profile/01417447499799468996noreply@blogger.com6