1:23, Monday June 11th, 2007 • feeling thoughtful • no comments
Facebook detects a user's timezone through JavaScript. A Date object is created, the timezone offset and sent back to the server via an Ajax request. This is done on every home page view, so at least every login and generally much more often. It's a simple technique and reliable, because it uses the value set by the visitor on their current computer, dates and times are consistent with the system clock in the corner.
12:53, Monday March 12th, 2007 • feeling thoughtful • no comments
For a new MyMart feature, we're allowing our members to customise the look of parts of the site.They can choose custom colours with a palette widget. The values they give us are used to generate a CSS stylesheet which alters the rendering of certain page items.
I wanted to write test cases to ensure that the CSS is being generated correctly, so I used Christof Hoecke's cssutils module to parse and then inspect the CSS.
cssutils parses a stylesheet into a hierarchy of DOM Level 2 objects. A stylesheet is typically made up of several CSSStyleRules which are broken down into a list of Selector objects and a CSSStyleDeclaration object which can be interrogated for the actual values we're looking for.
First pull the CSS text into a variable, load it from file, enter it by hand, what ever is appropriate.
Once we have the CSS in hand, parse it using cssutils'
parseString method.
>>> from cssutils import parseString
>>> pagecss = parseString(pagecsstext)
>>> pagecss.cssRules
[<cssutils.css.cssstylerule.CSSStyleRule object at 0x1480230>]
For the tests, I then need to search out and evaluate specific rules and values. cssutils doesn't make this as easy as we might like, my hope here was that I would be able to say something like pagecss.get_rule_for_selector("div.data-key") or something similar. There are problems with this for the implementor, I might request .data-key which should match in some situations. However, it would be nice to see a naive implementation added to the module. Here's one I made earlier:
def get_rule_for_selector(stylesheet, selector):
for rule in stylesheet.cssRules:
if hasattr(rule, "selectorList") and selector in [s.selectorText for s in rule.selectorList]:
return rule
We can then write expressions to get to the values of the stylesheet as follows.
Bringing it all together, here is my first test case. The page is served by Django, so I use their Client object to make a request.
class ShopTests(MyMartTestCase):
def test_shop_css(self):
c = Client()
r = c.get("/somebody/screen.css")
self.assertEqual(r.headers["Content-Type"], "text/css; charset=utf-8")
16:23, Monday March 27th, 2006 • feeling thoughtful • no comments
Another big advantage of effects-free programming is that it makes developing concurrent applications much safer. Current frameworks seem to stay away from the concurrency issue, each response is generated in a single thread and the web and database servers are used to enable concurrency. E.g. Apache worker thread contains a mod_python which contains an instance of Django. At least it seems this way. FastCGI does a similar thing, spawning multiple instances of the CGI to handle requests. All this means that the framework coder worries not about thread safety. This is a workable solution because HTTP is stateless, just get the cookie, pull the session from the DB and we're ready to go again.
To be quite honest, I'm not exactly what the implications of being able to do concurrent code more safely would be in this context, I just don't have enough experience in this area, perhaps the answer is that a Haskell-based framework would feel very similar in this respect. The coder working on top of the framework would not see concurrency-related stuff. However, I would expect that while Python and Ruby assert that no threading problems will leap up out of the framework and bite you, Haskell would guarantee it.
This does have implications for the framework implementation of course. A mod_haskell solution wouldn't be ideal, Apache's threads are more heavyweight than the GHC solution certainly and so would damage performance. Haskell would be a good candidate for building a FastCGI-based system, but it might be optimal to use HWS. However, HWS has nothing like the usage of Apache and so it's hard to assert it demonstrates the same security and reliability.
1:18, Wednesday March 22nd, 2006 • feeling thoughtful • no comments
One of my crazy plans for total obscurity (the inverse of world domination) is to try bringing some of the back cover benefits of functional languages to the web frameworks arena, basically to build a Rails or a Django in Haskell.
Well, first of all I've never used Rails, so I suck. So I downloaded it. Haven't done anything with it yet, but just to get it on disk is a big step (I'm on the Django devs mailing list for gawd's sake, though only as a lurker). It's all in the name of research guys, honest.
More than anything, this is an exercise in learning a language by applying it to a familiar domain. However, the advantages of implementing such a platform with Haskell are:
Non-strict evaluation and compilation provide greater efficiency. Data structure documentation with efficiency comments in big O notation can't hurt either :-).
Expressiveness and clarity of code, Ruby is a touch Perlish, though all the Rails examples are fairly pretty (this is DHH's stated goal for Rails after all). Django isn't quite so pretty perhaps, focusing more on practicality. Python and Ruby have some neat syntactic toys, but Haskell is the state of the art when it comes to expressive code.
Strongly-typed but with type inference. One of the great things about Django (and possibly Rails) and a feature I prized in InfoCMS was beautiful joyous harmony between the types used at the data layer and the types used at the interface layer. Forms are validated using information about the tables the data will have to later be injected into. Lots of very sturdy data types would be fantastically useful for this.
Removal of side effects. Side effects should be limited to the supporting layers that interact with the DB or with the OS etc, my code should be purely functional, allowing clarity and easier debugging and testing.
Now, I'm reading from the Haskell crib-sheet a bit here, and I haven't necessarily felt the power of these supposed advantages just yet, but it's all interesting theory.
On the other hand, there are some clear disadvantages compared to the way things are done in Django and Python at least, and I suspect Rails and Ruby too.
Haskell is a compiled, static language. Django's ORM for example, does all kinds of runtime dynamic magic to provide a slick programmer experience. Though they're removing the more magical magic, introspection is still a big part of the toolset. Particularly in the realm of data models and mapping, it will be hard to provide something as usable under compilation.
No objects, no variables even! My functional skills are not so leet. I've always been an OO boy. Learning to live without objects and side effects would not be impossible, but it's a huge paradigm shift for me and probably everybody else. Most web hackers want to make their lives easier, and while learning Ruby is a jump many have demonstrated their willingness to make, a whole new language paradigm is a much larger one.
Development speed. The great debate: strong typing, prevents bugs or just slows coders down? Everyone has to unit test anyway, so just catch 'em there. Now strong typing in Haskell is certainly no where near as much as a drag as in Java or C++ for instance, type inference whilst retaining both parametric and ad hoc polymorphism means a lot. However I'm certain that the code-compile-test loop sucks compared to edit-test. The compile step is a big drag on my hacking style, and GHC is not known for it's speediness in compilation. I remember hacking Java for wwWebflow and zoning out completely through compiles, so much so that I'd get really lazy and stupid when the time to edit and test came again. This could probably be solved by building a test environment which uses GHCi or Hugs in interactive mode. This would be a must really.
Discussion with Ladislav on Hypothetical centered around the problems of implementing the ORM layer without the O bit. Thinking about that now, I think the best way to go would be to allow a developer to specify rules for marshaling Haskell record types into tables (Django's doing this here). A good set of defaults would be provided, but allowing tweaking of the marshaling rules would allow tenacious DBAs to squeeze maximum performance from the application . Rules would ideally be written in Haskell allowing insertion of custom bits like index magic. Code for pulling records from the DB would be functional, the prevailing model would probably be to write query functions that get used by the controllers. It would be nice to have a Django/Rails/Class::DBI style interface, I just have to think about that some more.
Some of the concerns are deal breakers, but I'd love to test them in the wild. Haskell apps have tended to be toys a bit so far, with the notable exception of Darcs. I guess I kind of hope that there's some possibility that a Haskell web framework could garner some interest in the same way. I should just stick to Django probably :-).
I did actually write some actual code on Sunday, for what it's worth. Just some types for representing requests and responses really, all of which is already done in HWS. It felt good though.
I have a bluetooth dongle for my (old) Powerbook. I keep all my events in iCal and all my contacts in Address Book. I'm organised and I appreciate having this data on the run. So why do I never synchronise my phone to my computer? It only takes about five minutes, but it's just hassle. I have to take that five minutes out of whatever else I'm doing.
One alternative is to use wholly online services, with mobile versions, or browse them phone-side through Opera Mini. In my case I'm sure I can find a service that can provide WebDAV calendars for iCal and perhaps even LDAP for Address Book. Whenever I need to get to my information while I'm out, I just go to my bookmarks on my phone. But now I'm restricted to the places where I can get signal. If I'm sat on the underground I've got a powerful device with a large memory, but none of the data I need. This is something that a lot of mobile app developers seem to have missed. It's just about OK to assume that a desktop user has connectivity, as a mobile user it's in an out all the time and the bandwidth is dog slow. A much better experience will be provided to the user if you assume offline and be online if you get the chance.
So, instead, wouldn't it be great if I could use podcasting to get my contact, event and other data to my handset on a regular schedule? I'd set up RSS feeds for all of my key information, and those channels would include data in standard formats. For contacts, send vCards as enclosures, or use the hCards microformat. My phone would have options to poll my feeds regularly, I could do it on demand as well. In my case I'd set my phone to update every 24 hours, that would be plenty given how often I update and would keep my data traffic fairly low. If I'm out of range or battery when the allotted time comes, my phone would fail silently and retry later on. Perhaps giving me an error if a threshold of retries failed. My operator would provide a central service for uniting my disparate feeds (or I could do this myself), so my phone only has to check one place. If there's no new information, the data transferred is tiny.
The only problem with this idea is how to implement it. AFAIK it can't be done with a Java midlet because these must be explicitly run by the user. The whole benefit of podcasting here, as in other applications, is that it's a transparent background task. The user should not be involved.
Now some of you might say stop being lazy and get your Bluetooth on, but if you think this is an interesting idea, maybe we can get grass roots support to force it on the handset manufacturers and network operators :-). Maybe Dave Winer is reading right now. If you think this has potential, like to this post with the link text "syncasting" and we'll see what happens.
Actually, I did once meet a guy who did some UI work at Nokia and SE. Maybe I can twist his arm...