fREWdiculous!
14 Apr
For the benefit of my memory, my coworkers, and the rest of the intarwub, I am posting my expanded notes on the Ext Conference 2009. They are supposed to put up slides and video, so hopefully blog posts won’t be a major resource, but we’ll see.
I must give my impressions of things only barely related to the conference before I get into real content though. We are at the Ritz-Carlton, which is nice. But it’s expensive and the amenities are not worth the price. First off, the wifi isn’t free. Oh wait, the wifi in your room actually is non existent. So you pay 10$ for 24 hours of tethered connection. The wifi in the conference is free, but guess what, no power plugs aside from the few ones near the wall! My boss said I could get the wifi and expense it, but it’s still really slow. Streaming music just doesn’t work. I am streaming music fine over my G1 instead and that’s fine. Wait, maybe I could listen to the music on the cable TV! Oh wait… that costs too.
On another note, the conference is attended by an extremely diverse crowd. I think it would be safe to say that half of the crowd is not native to the US. There are something like 4 or 5 women though, so not entirely heterogeneous.
So with that aside, real content:
First off Douglas Crockford (you know, the guy who invented JSON?) did a very generic presentation on the future of Javascript. It was fun and encouraging, but won’t really help us for a long time. Numerous times throughout the conference it has been mentioned that IE6 is still very much dominant. I am very happy that most of our customers can be convinced to use at least IE7. There was a lot of fun history in Crockford’s talk, but I’ll leave that out for brevity’s sake. The next version of JavaScript (ECMAScript 5) is supposed to improve on a lot of the features of JS.
Browser interoperability is supposed to get a lot better because the implementations (browsers) will not be making as many decisions. Many common practices will be codified as parts of the standard.
Security is supposed to be improved upon significantly. The use strict mode (see next section) will help with that. Also objects can be “hardened” where they cannot be changed after creation. Same with properties on objects. But the global (window) still exists.
The strict mode is going to be optional. You shouldn’t use it in cargo culted code as it will probably break your code. It removes a bunch of “bad” features and could theoretically give better performance.
Some syntax has been relaxed. For example, if you do this in IE it will break: { class: ‘foo’ }. That is part of the spec and it is no longer an issue. Better yet, trailing commas are to be allowed!
All kinds of functions are added to arrays, objects, and functions to make them easier to work with. My favorite of course is a built in map
Regexps are better, JSON parsing is built into the browser.
But of course, IE6, 7, and 8 will be around for a long time before we can use this stuff, so don’t get excited. Just look forward to the future.
After that happens security needs to be looked into significantly. The current model is insecure if you ever include things like ads from external sites. It seems that a lot of that can be taken care of with Caja though. Interesting!
The next session was What’s New in Ext 3. As we all already know there is the lightweight core. It’s like JQuery or Prototype in that it’s a toolkit for websites as opposed to applications. It’s a subset of Ext so you will be able to use it with existing knowledge. It is Open Source (kinda, MIT.) It is unobtrusive and small. It has a great API and an excellent manual.
We have the new ListView, which is like a grid, but way simpler, so much more performant. Instead of a monster like Grid which can do everything, you just add plugins to allow it to do more. This is not supposed to supplant Grid.
Charting is very cool and surprisingly easy. Interesting things about it is that if you have say, a grid that shares a store with a chart, editing a value in the grid and saving it to the store will automatically change it on the chart. Very exciting stuff. Based on YUI charts.
Group tabs are kinda cool, but I doubt we will be using them any time soon. You’ll have to look at examples to see what they are.
The row editor for grids looks very cool. I can see using that, but again, you’ll need to look at it to see what it is.
Buttons are way better than before. They are sizable, stylable, and most importantly, you can place them anywhere as they can participate in layout.
Toolbars are now real containers, so you can put more stuff in there. Awesome. This allows things like ribbons etc.
BufferedGridView is a way to get better performance out of a grid. It only renders the rows that are visible, so it can make showing large datasets much faster. The only drawback is that the rows must have a static height.
The Debug Console is basically a way to have firebug in IE. Very cool!
HBox and VBox will be replacing Column and Row Layouts respectively. They are very flexible.
Ext ARIA is a way to get accessibility in your ext apps. It is currently not complete. The way you use it is by adding another js file to your include list and it will override a bunch of ext things.
resetBodyCss is a cool way to get your vanilla CSS back when you want it. So all of Exts CSS resets go away when you use this on a given panel.
I also went to the Ext.Data session, but I didn’t take very good notes because I already knew most of it from Ext 2. The few things that I learned were that Field classes represent the specific parts of a Record. I hope to override the date field so that it defaults to our date format. There is also a convert function that can be specified in a field on a record. Imagine a renderer, but much more basic. I also learned that mapping allows for mapping to actual objects and not just records. For example, if a record looks like this: {name: ‘frew schmidt’, currentLocation: { x: 10.23343, y: 4.32325 }}, I could define a field like this: {name: ‘yLocation’, mapping: ‘currentLocation.y’}. I could see using that in the future.
I also went to the Back to the Basics session. Again, I only wrote down things I didn’t already know. So semicolons are optional in JS. Did you know that can cause bugs? Example:
1 2 3 | return { foo: 'bar' }; |
1 2 3 4 | return { foo: 'bar' }; |
The second fails because javascript assumes you forgot a semicolon and puts it there for you.
And: how to make a singleton in JS:
1 2 3 4 5 6 7 8 | var Foo = function() { var privateGlobalFoo = ...; return { getFoo: function() { return privateGlobalFoo } } }();// <-- note the parens. |
Basically the parens run the function and return the value into Foo. If you try to call Foo as a function it will fail. Neat!
And lastly, I went to Ext.util. This session was very packed with info, so I ended up just writing down classes that I didn’t already know about to look up later
My list was: Ext.KeyMap, Ext.KeyNav, Ext.Editor, and String.format.
Other things I took away from throughout the day: testing is just not done in ext for the most part. A lot of people want it, but it’s just not going to happen. Dynamically configured grids are not that unusual. Extremely large datasets are not that unusual. There are lots of .NET and Java users, a few PHP users, and very few perl users. Almost everyone uses JSON and almost no one uses XML. The whole Ext team uses Aptana and maybe one other editor. Ext Designer should come for 3.1. An Ext Marketplace for extensions is planned. Theming Ext 3 will be extremely easy compared to Ext 2. Dynamic loading should be much easier in the future, though probably not core.
I’ll post again tomorrow. Hope you enjoyed it!
4 Apr
We all know programmers who, when they need to copy/paste more than one thing, just use a temporary window to keep track of the copied data. Well vim has that feature solved.
First off, we have multiple copy/paste buffers, known as registers. So I can copy and paste three different things into three different registers. To copy a line to register a, use “ayy. Then to paste that line you would use “ap. So we have plenty of registers. It gets better! What if you want to copy a bunch of stuff into one register? Well, first I would clear it with :let @a = ”, but that’s not required. Anyway, you can add to a register by using “Ayy. This will copy the current line onto “a. So you can do this over and over to add to the “a register!
But that requires too much work. Yesterday I wanted to add all lines with the word “name” into “a. Here is how I can do that with one line: :g/name/y A.
Awesome!
1 Apr
So in the project we are doing at work right now the customer has a fairly old dataset. Old enough that it originally was impossible to properly capitalize all of your words. I do a search and get a list of customers:
1 2 3 4 5 | AMERICAN AIRLINES SOUTHWEST AIRLINES A.O.G. L3 COMMUNICATIONS ... |
Why are you yelling at me?! I want to say.
Yesterday I had 30 minutes left in the day and I figured that I might as well do something that would make me feel good. I decided to make a DBIC inflator that would fix this issue. The idea is that in your DBIC setup you don’t just have Core, but also +ACD::SillyString and then when you configure your columns this takes care of recapitalizing things. You just add silly_string => ‘title_case’ to your column definition and it will DWIM. Maybe eventually I’ll add support for sentences. Also after I clean it up I’d like to put it on CPAN. We’ll see!
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 | package ACD::SillyString; use strict; use warnings; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/InflateColumn/); sub register_column { my ($self, $column, $info, @rest) = @_; $self->next::method($column, $info, @rest); return unless defined($info->{silly_string}); my $type = lc $info->{silly_string}; if ($type eq 'title_case') { $self->inflate_column($column => { inflate => sub { my ($value, $obj) = @_; if ($value eq uc $value or $value eq lc $value) { $value =~ s/(\w)(\w+ ?)/\U$1\L$2/g; } return $value; } }); } } |
On thing that I really like about this code is that it only applies to strings which are all uppercase or all lowercase. That way if the customer does correctly capitalize things, or wants to change the way that the code is capitalized by the model, they can. It really makes everything look a lot more professional.
31 Mar
Until recently most of the work I have done with DBIC has been very basic. I made a lot of simple classes, done some basic searches, paginated, and that was more or less it. The only thing in there that is really a major change from vanilla DBI was the pagination. Oh the glory of automatic pagination!
Well, recently I have been doing more complex things, and let me tell you, it has been a joy!
First off, Wes told me about the idea of a TO_JSON method. What I had been doing previously was in the controller I would list the columns I wanted from a class when I turned it into JSON. This is fine for the simple case, when all you want is simple data; but what if you want the data from a related table? Not so great. So I decided to set up TO_JSON methods for all of the classes. Now we just use whatever that provides in the controller. Sometimes we return more data than we would have otherwise, but since we paginate to 25 records by default that hasn’t become a problem. That cut the controller code down by maybe 25%. That’s significant in my book!
And then there are complex searches. Here is a scenario I had yesterday: the customer wanted to search in table X, which is related to table Y, based on some criteria for Y. In DBI I would have had to define a join blah blah blah. Because I predefined the relationship from X to Y in the model class, this was my search:
1 2 3 4 5 |
That’s it for now, but I am sure this story is not over…
28 Mar
I’m sorry that I’ve neglected this blog so much the past couple of weeks. I will give excuses promptly, and then I will immediately follow that with another post that you will hopefully find of value
So I was fairly sick this week and that really killed my output. It’s hard to pursue what you love when you don’t even feel alive. Turns out a lot of my friends got sick around the same time, so I image that something is going around. The irony (tragic, according to Meriam-Webster) was that last week was also when we had decided to demo our customer’s product.
And that is a great segue into what this post is about: how we do demos for our customers.
We do a loose form of agile development at my company, mostly due to the lack of much organization or planning as a whole. In general I think this is a good thing. On the project I am working on we are trying to do something closer to SCRUM. We haven’t quite mastered it yet, but we are doing iterations and demos for our customers and Neil and I meet every day to talk about progress. I am not quite organized enough at this point to keep up with a burndown chart and I keep forgetting to even do anything with the bug tracker. We are getting there nonetheless.
The point of my digression there is that we do these demos for the customers, but instead of just showing them all of our features we try to take it a step further. Features are great, but if the program is hard to use it doesn’t matter.
So what we do is set up a GoToMeeting session, I explain how we are in the project timeline to make the guys with the money happy, and then we give control to whoever will be using the feature we have completed. We give them a few directives but no directions, or at least as few as possible.
Usually they figure stuff out, but it is interesting to see what they try, and that gives us a good idea of how they think. For example, yesterday we were demoing a user system with groups. The way you would add/remove groups from a user was to drag the groups from/to a couple of grids. Seems simple enough. But the user tried to drag available groups onto the user data instead of into the user’s groups.
So when I get the chance I will make it so that that works too. The other interesting thing is the following conventional wisdom: users don’t read directions. I know that’s true, but every now and then you think, “hey, this is something that’s not perfectly obvious, so let’s put a but of text in there to make it clear.” We put something like six words in this panel, and they were at 25pt font. Guess what? Even though they were on the panel that they explained, the user didn’t read them. I may or may not leave the words there, with the knowledge that they currently just clutter up the page.
There are numerous reasons to do demos this way. They give the customers a sound mind that everything isn’t just faked. We can see what we are doing wrong from a design perspective. The customer can raise objections about possible misunderstandings we may have had. And with a user base as small as we have, we are also training them in the new application piecemeal.
And it looks like I may have to put off that other post as I have a hot date now
Have a great weekend, and stick to your requirements!
21 Mar
Furr by Blitzen Trapper
is the Album of the Week. This post (as well as 2-3 others) should have been done earlier in the week, but I was a little swamped. Sorry if you were on the edge of your seat
So Furr has definitely been my favorite album this week. I can tell because Last.fm tells me I have listened to it ELEVEN TIMES in the past 7 days. I would describe the style as somewhere between Neko Case (indie country) and Bob Dylan. I have also seen the band compared to Neil Young as well.
Their style is also slightly erratic, with songs like Fire & Fast Bullets, which brings OK Go to mind, and then Gold For Bread which is more like older rock, but with weird noises in the song at some parts. Very intriguing music.
Factoid: both Furr and God & Suicide have been on the NBC show Chuck. You may not like that show, but it definitely has lots of indie music (whatever that means.)
I dig the lyrics. The first song that caught my ear, Furr, is about the transformation from man to wolf to man. And then we have Black River Killer:
Then I went to the river for to take a swim
You know that black river water is as black as sin
And I washed myself clean as a newborn babe
And then I picked up a rock for to sharpen my blade
Favorite songs: Furr, God & Suicide, Black River Killer, Fire & Fast Bullets, Saturday Nite, Gold For Bread.
Colors: Tan and Brown.
15 Mar
Hopefully everyone reading this blog knows the function map. Map maps one array onto another with a simple function. For example, if I had a list of names at my old school and I wanted a list of emails I could do something like this:
1 2 | my @names = ('frew schmidt', 'bob barr', ); # etc... my @emails = map { s/\s+//; "$_\@letu.edu" } @names; |
I think that’s pretty great. I thought it would be cool to reinvent the wheel and implement map in Perl 6. One of them will be implemented the typical way and the other will be the Perl 6 (as far as I can tell) way.
Here’s the obvious way:
1 2 3 4 5 6 7 8 9 10 | sub map1(Code $fn, @list) { my @new_list; for @list { @new_list.push($fn($_)); } return @new_list; } map1({ $_ * 2 },[ 1,2,3,4,5 ]).perl.say; map1(sub ($f) { $f + 2 },[ 1,2,3,4,5 ]).perl.say; |
Pretty simple. We make a new list; iterate over the original list and push the value returned from the code onto the new list. But look at how much we have to think about the new list! The important part is the operation, not the list, or at least that’s what I think.
With that in mind, map round 2:
1 2 3 4 5 6 7 8 9 10 | sub map2(Code $fn, @list) { gather { for @list { take $fn($_); } } } map2({ $_ ** 2 },[ 1,2,3,4,5 ]).perl.say; map2(sub ($f) { $f ** 2 },[ 1,2,3,4,5 ]).perl.say; |
Gather/take, as mentioned previously, abstracts the idea of creating a new list.
And as for a question that Sol mentioned previously about gather and take:
… is gather / take just syntactic sugar, or is it implementing lazy evaluation, or is it even opening up the possibility of threading?
I think that gather/take is really just a pretty syntax. I think that it depends on what is inside of your gather for what is possible. You could even iterate over the contents of a file inside of a gather, in which case I am sure you couldn’t do threads. I guess lazy evaluation is theoretically possible though… But that would depend both on what is inside of the gather and what uses it.
12 Mar
I was hoping to work on the setting for Rakudo some today, but it just wasn’t happening due to my own inferiorities. I decided instead to try to read some of the setting code so that I can be less inferior in the future. I hope you enjoy learning some Perl 6!
First we’ll start with a simple one: Str.lcfirst.
1 2 3 | our Str multi method lcfirst is export { self gt '' ?? self.substr(0,1).lc ~ self.substr(1) !! "" } |
our Str multi method lcfirst is export: our means public; Str means it returns a string; multi means it can be defined with other method signatures etc; method lcfirst is the name of the method; and is export means it also becomes a function.
self gt ”: this just returns true if the current string is greater than ”, which will be true if it’s not blank.
The ?? thing is Perl 6′s tertiary, ?? !!; which is ? : in most languages. I think ?? !! is a lot easier to remember because it’s like, “is this true??then do that; !!otherwise do something else.” Thanks Larry
So if the current string isn’t empty, we do self.substr(0,1).lc ~ self.substr(1). This is the meat of the function. This basically says, starting at the beginning of the string (0) give me a 1 character string, then lowercase it, and then concatenate it with a string starting at the first character that goes all the way to the end.
And if the string is empty we just return empty. That wasn’t so hard was it? Next up: split!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | our List multi method split($delimiter, $limit = *) { my Int $prev = 0; my $l = $limit ~~ Whatever ?? Inf !! $limit; my $s = ~self; if $delimiter eq '' { return gather { take $s.substr($_, 1) for 0 .. $s.chars - 1; } } return gather { my $pos = 0; while $l > 1 && $pos < $s.chars && defined ($pos = $s.index($delimiter, $prev)) { take $s.substr($prev, $pos - $prev); $prev = [max] 1 + $prev, $pos + (~$delimiter).chars; $l--; } take $s.substr($prev) if $l > 0; } } |
I won’t explain anything again if I already explained it once. So the first new thing we see here is an actual method signature. $delimiter: this means we have a $delimiter value passed in. $limit = *: somewhere Larry Wall wrote that he imagined a language called STAR in which verbs would all be * and they would just DWIM. This is related to that idea. We’ll get to it when we use $limit.
my Int $prev = 0: we are defining $prev to be only an integer and it starts off as 0.
my $l = $limit ~~ Whatever ?? Inf !! $limit: * has a special relationship to Whatever. Whatever is a type of *, so * does Whatever. The idea is that we are matching $limit with whatever, which in this case means only true if the user passed in a value for $limit. Otherwise $limit gets set to Inf, which unsurprisingly means infinity. A little weird. I may clarify this later.
my $s = ~self: We are coercing self into a string here.
return gather: gather/take is a really cool control structure that lets you generate an array without any temporary variables. So you pass gather a block and then any time take is called in the block it pushes the value passed to take onto the generated array. Pretty awesome right?
So the first gather is called if our delimiter is ”, which means get the string as an array. We iterate from 0 to the last character in the string, and give the value of the character (single character string) to take. Fairly simple besides grokking gather/take and wondering where $_ came from till you see the for later on in the line.
The next half of the method basically repeats over the whole string looking for delimiters. It has the following conditions:
we haven’t split more than we originally intended (limit)
and we haven’t gone past the end of the string
and we have a position on the next delimiter in the string
Then we take the string starting at the previous delimiter till the position of the current delimiter. I personally would have defined $prev inside of the second gather as that is the only place that it’s used, but that’s just me
Next we set $prev to the maximum of one more than the last delimiter and the current delimiter + the length of the delimiter. This is a really strange line of code, but so it goes. First off, we are using the reduce operator ([]) to find the max. I would have used just max as we are only comparing two things; not a big deal of course. I also cannot think of a time when the first option would even be greater than the second, only equal to it. I am probably wrong though…
Then we decrement $l, which is our max amount of splits.
And then we end by taking the rest of the string if there are any “splits” left. Again, the if statement there seems superfluous. But I could be wrong.
I tested my theories about extra code and it still seems to work fine. Here is my new and imFrewved method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | our List multi method split($delimiter, $limit = *) { my $l = $limit ~~ Whatever ?? Inf !! $limit; my $s = ~self; if $delimiter eq '' { return gather { take $s.substr($_, 1) for 0 .. $s.chars - 1; } } return gather { my Int $prev = 0; my $pos = 0; while $l > 1 && $pos < $s.chars && defined ($pos = $s.index($delimiter, $prev)) { take $s.substr($prev, $pos - $prev); $prev = $pos + (~$delimiter).chars; $l--; } take $s.substr($prev); } } |
11 Mar
Another tutorial posted here. This goes over functions, references, regular expressions, and perl’s case statement (given/when).
Enjoy!
11 Mar
Brave by Marillion
is this weeks Album of the Week. Before I get into specifics I need to tell a story about how I got into Marillion…
I found out I loved prog music because of Transatlantic. Marillion’s Pete Trewavas is one of the members of Transatlantic. I checked out all of the other band member’s groups, but I never did check out Marillion (as in order a CD.) One day I was in the thrift store and I happened upon a Marillion album (Season’s End
.) It was surprisingly good and I bought up a few more albums (Misplaced Childhood
, Fugazi
, and some other one I can’t find.) Anyway, I just cannot believe that I found music that excellent at a thrift store.
Back to Brave. Brave is one of the earlier Marillion albums, yet it still falls into the “Hogarth” era Marillion. I would compare Marillion with Radiohead, except I don’t really like Radiohead enough to know them that well. Marillion often has fairly dark music, and Brave is no exception. I have never actually noticed the lyrics on Brave (except for The Great Escape,) but Brave is a concept album. I recommend reading the lyrics instead of listening to me about that though.
I would also describe this album as very heartfelt; that is, I would say that feeling and meaning tend to bleed through. I would compare this to how I feel about The Arcade Fire.
Brave is one of those albums that you really should listen to in its entirety. It has a great intro and an excellent finale. Brave is a good album to listen to when it’s pouring rain out and you just feel like brooding.
Favorites: Bridge, Living with the Big Lie, Hard as Love, Brave, The Great Escape.
Colors: Black, Navy.