< prev 4 Feb 2015 to 14 Jan 2015 next >

Posts tagged 'backbone'

  • The Data Model

    One of my hangups about continuing work resolved itself over the past couple days. I ended up having a couple of redundant checkins—"Fixes data model", "Data model finally fixed"—but I think I'm there now.

    Collections have models, and certain models, like Posts, have collections of their own (in this case, comments). When you pull the data from the server for a non-root page, the data needs somewhere to "hang" so as not to face sync problems. So, when I fetch a post, I shouldn't fetch the class it belongs to, I should instead examine the post's section_id property, and then put that in an existing class's post collection. … Got it?

    User -> Sections Collection -> Section Model -> Posts Collection -> Post Model

    So, on fetch of the last item in that chain, I need to go to the head of the chain and request that this data goes in the proper place in that chain.

    It took me a while, but I think I ironed out all the kinks. It took moving some logic from the models into the collections: if you ask a Post what section (class) it belongs to, it asks its collection, which in turn had that property set upon initialization. (I also needed to start initializing new collections with (null, options) instead of ({}, options) because it turns out {} is a model on its own, just one with no attributes… derp.)

    What does this mean? A whole bunch of crazy sync problems disappeared all at once, and I can finally see the light at the end of the tunnel. I have never truly had a Minimum Viable Project (MVP), and I'm getting to the point where that feels possible, and likely to happen soon.


    Now that we don't have to blog, I can blog whenever I want—which also means blogging in the middle of the day when I've found some solution to a particularly knotty annoyance and am taking a break from whatever.

    I'll try to keep this quick, and I still don't have it how I want it.

    Sign-in is handled through a modal (using a library that is just okay…). When the app first starts, it tries fetching the currentUser model (asynchronously, of course). Meanwhile, it tries to route to whichever route was input, and if the user isn't signed in (which he won't be, because we're still waiting on a server response), it redirects to the sign-in window, which has an initializer that tells it to destroy itself when it receives a 'signIn' event over the Backbone.Radio eventsChannel.

    Meanwhile, the modal animates, and only adds its keybindings once the animation is finished. But the 'signIn' event is received in the middle of the animation, which means that the view is destroy()ed before it has attached its keybindings… which it does after the fact.

    Long story short, when a signed-in user refreshes the page, the sign-in modal installs listeners that get uninstalled before they're installed, and the next time the user hits "enter" the modal executes a "submit" event on empty text fields.

    I got around it by having an onShow callback that checks to see if we're signed in, and ONCE THAT CHECK HAPPENS, install the 'signIn' event listener. If that check fails (we've signed in during the 100ms that the animation has as default) then we uninstall ourselves.

    Gah. JavaScript, why you hurt so much?

  • The ghosts of problems long dead

    Friday, I thought I had sign-in working the way I wanted. Saturday, I spent the day wrestling with the order that actions hit in Javascript.

    I am hesitant to say that I think I've got it, but it makes a lot more sense—no matter what path someone takes to a URL, make sure to bottleneck actions that need to take place in a certain order in order to make sure that everything related to cleanup happens when it should.

    Originally, the sign-in model we were given had login set with async: false, which is deprecated and rightfully so. A good portion of my day was spent looking at a repeated message from JQuery stating as much, and once I figured out what needed to happen—the user, on sign-in, throws a signIn event that other objects subscribe and respond to—I was most of my way to getting the interaction happening the way I want.

    This is a lot of wasted time, but I have to say that I really understand async events much better now, as well as pub-sub. Whenever I think I know what I'm doing, though, I learn more, so I'm reluctant to say that I know everything I need.

    One other thing happened in that was particularly frustrating. I removed my homebrewed utils directory from the manifest, only to change my mind and keep it in to be able to take advantage of a couple that I thought were useful. Well, for two hours I was getting weird behavior that, it turns out, was caused by my own implementation of router callbacks. Whoops, shit. I'll have to keep an eye on that sort of thing in the future.

    I've noticed that it's nice using a common naming scheme when creating files, but it often makes it challenging to figure out which show.js you need to be editing, or is throwing the error you're looking at. It pays to take the three seconds to verify what you think is happening is what's actually going on.

    I had a similar problem with Wordpress—I was making changes that didn't seem to be showing up in the final render, and I went down a lot of paths before I figured out that there are actually three different blog post views: all posts, posts by category, and single post. That's not DRY at all :(

  • Never have I been so happy to get a blank screen before

    Holy crap. I wasn't sure if I could do it, but I've got my app rendering a blank screen.

    Some elaboration is required.

    I set out today to get the basic infrastructure of Marionette working, with a modal login screen, and a router before action that properly redirects after sign-in.

    At 9:30 tonight, I checked in the last code that was necessary to get this to happen.

    I am so happy. I thought, when we were first learning Backbone, that it was pretty opinionated, but it turns out that it's flexible, and requires more configuration than convention. Sure, there are things that backbone-on-rails tries to enforce, but that's not Backbone per se.

    Marionette, on the other hand, has some strong opinions, but the documentation is sparse enough that it can be hard to discern what those opinions are. Nevertheless, it desires certain things, and after a lot of secondary reading, I have figured out a lot of what those things are. For instance, Marionette wants you to modularize everything, but the Marionette.Module object is pretty ghetto and is slated for deprecation.

    In the meantime, then, one can use standard JavaScript modules and so forth to add in modular portions of an app, or (as I have) simply expand on the backbone-on-rails opinions by adding a folder for (e.g.) controllers and inserting it at the correct point in app startup. It works for now, but I may have to refactor later.

    And what a statement that is! Every single line I wrote in Backbone felt like it needed serious refactoring, but everything in Marionette is so DRY. Sure, there's a bit more "needless" code to pass messages, but that is in keeping with the spirit of loose coupling.

    Case in point: I spent a good deal of time learning about JQuery Deferreds, which are a means of handling promises in JQ. They're similar in behavior to Arel queries—they don't do anything until you resolve() them, and until then you can keep modifying them by tacking on further attributes. Pretty cool, if you ask me, although a bit of a trip to wrap your mind around. When reading Essential JavaScript and coming across the section on promises, I didn't quite understand them, only really understanding that they help cut down on callback hell… but I saw the reason for them. Now I think I can consider them a part of my toolbox.

    What did I do today, then?

    • Marionette is starting up
    • I have created regions
    • I can attach subviews to the correct region
    • Calls to routes that require login are properly intercepted
    • Once login succeeds, the original route is triggered
    • Login is actually working :)

    What did I learn?

    • Reading the docs, while essential, can only get you so far
    • At some point (earlier than you [ed: meaning 'I'] think) you need to sit down and just break things
    • Initially, at least, you're not going to have a damned clue what you're doing, so you have to just get the gist and then try things.
    • Act more than plan. (This is personal, and in reference to my current state.)
  • What next, indeed?

    I did make headway finding employers today, which is good. There are quite a few that I can tell are doing things I would enjoy, now that I know how important user interactions and a strong API are to me. All the glue in the middle is not so interesting, which suggests, me being me, that this will be my first role out in the real world. Lol.

    Most of the work just involves reading corporate copy and trying to suss out what it is that a company actually does. I will say that if I can't understand a company after two or three reads, they don't go on the list at all.

    As for the rest of the day, I spent a lot of time stressing out about getting my project portfolio together. I still don't love my final project, but I started doing some major refactoring late yesterday afternoon and well into the night, and even though I haven't tested what I'm writing as much as I'd like I know that I prefer Marionette.

    My project won't be done in the way I'd like, but as long as I can show it off, it should be okay.

    This is stressful.

  • Ducks in a row

    Yesterday, Tommy asked to sit down with each of us at some point this week, to see where we are and what we're working on. I grabbed the first slot, and basically asked him "so, what are we supposed to be doing this week?" The list of tasks is pretty daunting at the moment, but today I feel like I'm getting a better handle on everything that needs happen in the forthcoming weeks.

    In short: I need to figure out how to best identify jobs to apply to, I need to compile those into a "roadmap" of places to apply, I need to (at some point, starting next week) apply to them… and to prepare for that, I need to get my portfolio, resume, and cover letter together.

    Speaking of that, I did some work on my personal website (where you're reading this) (ed: this is no longer true; I'm on a different site now), and learned quite a bit about how Wordpress works. It's okay, but I still kind of hate PHP. In time I'll probably get it more to my liking, but it's functional now, at least.

    Again, the coming priorities are portfolio and job searching, and how daunting they are! I've decided that I have more to do than Backbone can handle, so tonight I started reading into Marionette. It's not something that happened as a lark; I found myself doing so much repetitive stuff in Backbone, and the solutions I found always seemed to lead to Marionette anyway. Finally, tonight, upon turning my attention to my final project again, I found myself installing three plugins to add functionality that Backbone didn't have and that I didn't much feel like writing… and said, to hell with this, I'm going to do it right.

    It looks like a pretty good drop-in add-on to Backbone, so I'm pretty confident about the possibilities. I told Tommy, though, that I'd have it together by Monday, which is going to take a lot of my time. Here's hoping.

  • Week 9 Day 5 - Presentation Day

    Well, not much to say… Today was presentation day, and I spent most of the day bug chasing, trying to get core features to work the way they needed to work and not the broken ways they had been. I feel like Javascript has more instances of dodgy edge behavior than any other language that I've worked in…

    Afterward, my peers and I spent a good amount of time talking about previous classes' projects. We thought, two weeks ago, that other people's projects weren't very good, but we came out today understanding just how hard it is to produce production-quality code in a short time period.

    I pretty much faceplanted on the presentation portion of the day. I want to go back to this project, to finish it up, but I know it can take as much time as I'm willing to give it over the next three weeks, or I can find other projects to also work on… time management will become even more important over this last period. Thankfully, we don't have to go in until 10:30 Monday, and this weekend will be a much appreciated break from the slog that was the project week(s), but … what will my portfolio look like? The pace doesn't ever end. What next? I have a book on Objective C, and an Arduino kit here, and I know that my portfolio might be able to say a lot about me, but what do I want it to say.

    Back to work Monday.

  • Week 9 Day 4 - Down to the wire

    Spent most of the day today trying to make up for lost time, which doesn't really work but most of the day I had that level of speed. I left the office at 11:00 last night and midnight tonight, and got in a half-hour late this morning because there just isn't enough time.

    A benefit to overthinking everything and going down blind alleys is that my bug-hunting skills are only getting better. After three productive hours prior to lunch doing… I barely remember, but something… I tried doing something a bit too clever (having to do with separation of concerns again), and didn't come up for air until after 6. From 6 to midnight I was plenty productive, but messing up like that still stings.

    In brief: I monkey-patched the Backbone Router prototype to offer callbacks before and after routing, and then tried using those hooks to grab a user who wasn't logged in and redirect them to the login page (while preserving state). Once again, on my way home, I think I understand what I was doing wrong, and can see how to fix it, but I ended up ripping most of that code out and leaving it basically exactly how we were taught in the auth demo.

    I still don't like having a currentUser global, but for my app it's not a terrible idea, since you need to have some purpose coming to a blackboard-like site. It's not like your typical modern website, where there's generally some functionality that's meaningful even without an account, so… whatever.

    Oh, so I remember now—one of the fastest ways to make me hate your website or app is to have data entry be painful. So I spent three hours making syllabus creation absolutely beautiful, modulo a couple tweaks, and ran into a bug that I couldn't figure out even with Tommy's help. Basically, I had the event creation success callback call a JQuery focus() event on the first field in the form, and it kept losing focus after render. So I said to hell with it, and installed a setTimeout call that waits 50ms then focuses back on the first field. Hacky, but resilient.

    No matter what I do, more of these sorts of hacks creep into my codebase. But then I see things like when iOS autocompletes a word, then you press punctuation, it backspaces and writes the punctuation and a space instead of just inserting it at the previous position.

    I can't decide if this says more about the UX rot of iOS or the inevitability of hacky solutions.

    Tomorrow we're presenting again and I think I'm going to bum rush the core features, no matter how they look, rather than polish anything. I have a TODO.md full of broken things, but that's just going to be the nature of the beast.

    Wanna know what kind of day it's been? I just remembered that I didn't eat my breakfast. I packed it in my bag 16 hours ago.

  • Week 9 Day 3 - The one good thing

    … about everyone having a slow day is that you can commiserate.

    I spent a while this morning moving items out of my TODO list and into Trello—might as well use it for something now that I have an account. I found that trying to read to-dos off of a serial text file is next to impossible, and until I can afford a more full-featured project management app, it should do the trick. (Why is OmniFocus so expensive?)

    From there I went down a rabbit hole of other people's code, doing a lot of thinking about separation of concerns and where and how views should interact, and how routers play into all that. The good thing is many people have asked themselves similar questions before; the bad news is that so many people have thought about it that there's no one good answer for how to address it, and Backbone is agnostic about the whole mess.

    That was most of my day. I did read a lot of code and learned more and more about how Backbone actually works under the hood (as well as playing with a number of neat Underscore functions) but at the end of the day what I have to show for it is clickable column headers that update the sort order of their associated table, and some utility code … not so much output.

    I'm already thinking about what I want to and need to do tomorrow, and prioritizing various tasks based on the knowledge that we'll probably have a 1-hour lecture at some point and that we have to present again on Friday… It's going to be close. Hopefully I'll have some "wow" by then.

  • Week 9 Day 2 - Movin' right along

    Today was the .css assessment, and after working late (and falling asleep while working a few times) and doing the practice twice, then studying the solutions last night and this morning, I kicked ass.

    To summarize: good design often has a logic, and good instructors are consistent, almost without fail. If there are exceptions, they are for a good reason - your instructor is working at the forefront of the field and the rules aren't established, the design language you're working with has some foibles that you have to work around.

    In our case, I've managed to pick up on and benefit from the design habits of our CSS specialist, Jonathan, and have slowly been trying to incorporate them into my own design language. For instance, set consistent (and generous) margins/padding, keep visual space symmetrical, tend to favor making item borders on the inside and container borders on the outside, … and so forth. I haven't built all of this into my site yet—it still looks like baby's first webpage, although thankfully not as 90s as all that—but there are a lot of things coming together very quickly.

    Case in point: investing in figuring out backbone means that I've basically added three full collections, three full models, and half a dozen views to my app today alone. I also added two utility … packages? files? to my app that enable some neat stuff, one that makes my life easier, and another that enables a pretty cool "live search" feature to the website.

    Yeah, it's all pretty silly overall—I'm reinventing the wheel—but I know why and how I'm reinventing the wheel here, which is okay by me.

    There's very little of what I'm doing that is really challenging now, which is okay after the weekend. To use a workout metaphor, this is my plateau, where I'm consolidating gains before looking for more of a training effect. Again, I'm okay with that.

    Meanwhile, I'm able to explain to a lot of people what their code is doing wrong, or able to sort through arbitrary code and understand it pretty idiomatically; I'm much more confident with git and am aliasing my most common commands regularly, and can find my way around Atom like nothing.

    Wow, they have taught us something. :P

< prev 4 Feb 2015 to 14 Jan 2015 next >