|
LATEST POSTS
Saturday, May 01, 2010
Before I get started, I should point out I may have a shaky definition of the term “multitenancy”. I haven’t exactly studied up on it but I’ve skimmed some blog posts and I hope it means what I think it means. In our Google Web Toolkit application, we’re going to have multiple clients but only a single instance of the app and only a single data store. Multiple instances of the application and the data store aren’t feasible as we are deploying to Google App Engine. That makes it sound like Google App Engine dictated the solution but it was more of an “icing on the cake” thing. Even if we were doing it in SQL, we were going to do it in one database. I think one reason was to make it easier to aggregate data but I hope there were more reasons because that one is kind of lame. After all, we could aggregate all the data we want into a separate database for reporting purposes. We’d like decent URLs as well, like http://wholesaleroadkill.com/store/clients/crittersnstuff and http://wholesaleroadkill.com/store/clients/macysHairSalon. This isn’t as easy as it sounds in GWT because the default behaviour is to load the app and manage all transitions as AJAX calls. If you need to bookmark something, it’s done with a hash tag. Some examples: - http://wholesaleroadkill.com/#clientList
- http://wholesaleroadkill.com/#inventory
- http://wholesaleroadkill.com/#category;mammal
I like to compare the type of applications you build in GWT to GMail. Once you hit the home page, you stay there. There isn’t really the concept of navigating to a new page, just refreshing sections of the existing page. Furthermore, GMail supports multi-tenancy to some degree. If you use Google Apps For Your Domain, your home email URL is http://mail.google.com/a/wholesaleroadkill.com. After that, navigation is done the traditional way (e.g. #sent, #drafts/123123123, #inbox, etc.) Problem is, as far as I know, GMail isn’t a GWT app. And even if it is, it’s not open source so how they configure it to be a multi-tenant application is for me to find out. I’m told that multi-tenancy is on the radar for GWT but the radar sounds pretty big so I’m not holding out hope. So I did find out *a* way to achieve what I want, through modifications to the web.xml config file. By default, the home page for your GWT application is <appName>.html. It’s a physical HTML file located in the war folder. It contains everything needed to load the JavaScript that powers the app. In ordered to set up the URLs, I modified web.xml to redirect requests to this file, like so: <web-app>
<!-- other stuff -->
<servlet>
<servlet-name>Multitenant</servlet-name>
<jsp-file>/myapp.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>Multitenant</servlet-name>
<url-pattern>/myapp/customer/*</url-pattern>
</servlet-mapping>
</web-app>
With this in place, I can navigate to /myapp/customer/freddystaxidermy and /myapp/customer/thelmasgunemporium and have it serve up myapp.jsp. MyApp.jsp is almost an exact duplicate of MyApp.htm with one change I’ll get to later.
Don’t let the use of session scare you. Done the right way (and they make it very hard *not* to do it the right way), it’s actually using the Google App Engine data store to manage the session. From what I can gather, it’s actually the recommended way of managing state in a Google App Engine application because of the speed and scalability of App Engine.
There are some considerations to this approach that I don’t know I’ve thought through completely. The big one is security. Every call needs to be qualified somehow to indicate which customer is making it. I.e. which URL launched the request. For the moment, I’m doing that by making a call in the main page that sets a session variable based on the URL. This kinda reeks of being very open to allowing someone smarter than I am to make a call with a fake URL and impersonating someone else. At the moment, that’s still a pending todo.
Back to the change I made to MyApp.jsp. We had a relative reference to our CSS stylesheet:
<link type="text/css"
rel="stylesheet"
href="myApp.css">
This doesn’t work because it’s now looking for myApp.css in the wrong place so I changed this line to:
<link type="text/css"
rel="stylesheet"
href="<%=request.getContextPath( )
%>/myApp.css">
Now it properly references myApp.css at the proper level of the application.
This brings up an interesting aspect to this set up. There are still certain things, like myApp.css, that are accessed globally. We are using gwt-platform, which uses a modified version of gwt-dispatch for server-communication. All requests are routed through http://wholesaleroadkill.com/myapp/dispatch regardless of where it originated. I’m sure it can be configured so that requests are routed through http://wholesaleroadkill.com/myapp/customer/freddystaxidermy/dispatch but that hasn’t crept high enough on our priority list yet.
Note: I’ve had this post ready to go for a few weeks now. Typing it out made it sound more hacky than it did when I figured it out in the first place. So consider this an appeal for alternatives or tweaks.
Kyle the Let
Wednesday, April 28, 2010
My marketing skillz aren’t the greatest. Which is probably why two of my three favorite sections of Brownfield Application Development in .NET are available free. The one that isn’t is chapter 1 which I like because it opens with a sample brownfield scenario. It was the place where Donald and I could be most creative. I’ve attached my own homegrown excerpt from that chapter but I’m not entirely sure what the official procedure is for doing that so grab it before I get in trouble. The second section I’m proud of wasn’t written by us. It’s the foreword by David Laribee. He was our first choice to write the foreword for a few reasons. First, he was there at the beginning providing encouragement to write the book in the first place. Second, his writing style jibes with ours. And third, we knew he’d make us look good. That third reason is why I’m proud of it because he came through in spades. The third part I like is pretty much all of chapter 6 which is freely available on the book’s site. It’s unassumingly titled “Defect management” which sounds about as exciting as a discussion on Russia’s economic policy. Well, it turns out Russia’s economic policy can be pretty entertaining when you look at it from the right angle. As we wrote and re-wrote the chapter, a funny thing happened. A theme emerged. I’d heard of themes before from, y’know, legitimate writers and stuff. It never occurred to me that I might actually create one, however inadvertently. We wrote the first draft of the chapter pretty much as you’d expect a chapter on defects to be written. Then we forgot about it until the next pass. By that time, we’d finished the first draft of the book and had a better sense of how the whole thing should flow. And chapter 6, coming as it did at the end of part 1, seemed like a logical place to try our hand at being inspirational. In some respects, a brownfield project is defined not only by its defects but by the team’s attitude toward them. A large backlog of defects sends a message to the team: These defects aren’t the most important thing in our workload. Maybe the team (and by team, I mean developers, QA, client, project managers, etc.) had reasons that seemed good at the time when the defects started piling up. New features needed to be pushed out. The defect was going to be addressed after rewriting the UI layer. It was due to a defective third-party web service. But at some point, a prioritization decision was made before the developer started a new task. And unless the developer started picking off defects, the decision was: something else is more important than every single defect in this list. There’s a psychological barrier to fixing defects. They’re boring. It’s code we’ve already written and don’t want to look at again. New features are more fun. And more profitable. There’s always the risk that we’ll submit the fix and it’ll come back again and that we’ll be saddled with this defect for the rest of our natural lives. Customers often learn to live with defects so who are they hurting really? I’m in the early stages of a start-up and to date, I’ve been the sole developer. In the next month, the development team will triple and today, we had a discussion on team culture. As a solo developer, it’s much easier to be lax when it comes to letting quality slide. After all, who else is looking at the code? Don’t we have *real* deadlines to meet? But such is the thinking that leads to brownfield applications and it is *not* something that we are willing to stand for in our greenfield project. We are placing a high priority on code quality. Not because we want to blog about how cool it is to write good code and how superior we feel because of it. But because we believe very strongly that high quality code will save us a boatload of money in the long run in ease of maintenance and flexibility. You can see how a discussion on defects can lead to one on culture and the priority you place on quality. I believe in the benefits of TDD and BDD and mocking and IoC containers and OR mappers and all the other things the kids are developing with these days. But what good is all that if, when defects are found, I ignore them? Worse yet, what does that practice tell the two new people coming in, one of whom is a junior developer? Seems a little too hippy-critical for my tastes. So while we started out talking defects in chapter 6, these kinds of issues started bubbling to the surface. What type of culture do you want to install in the team? How can you achieve and maintain a zero defect count? How do you place a high priority on quality while maintaining a decent pace on productivity? It’s been a while since I re-read the chapter so I hope the answers to some of these questions are in there. But the part I’m proud of most is the fact that we even asked the questions. Kyle the Morphed
Wednesday, April 21, 2010
This is kind of a “here’s our thought process” type thing on a specific user experience issue we’re having. It’s inspired partially by Joey Beninghove’s recent foray into entrepreneurship, something I’ll be following with interest as my friend and I tackle some of the same issues. The discussion we had today was on searching, which has always been kind of a side interest of mine. We’re working on a search screen for clients. The basic requirement is: user enters text and the screen finds clients. We’ll search for the text in the first name, last name, or email address. I’m a fan of the single textbox and single button approach to searching, like the one used in iTunes and Windows Media Player. I can’t imagine having to navigate a complicated search form to search my music library. If I search for “blue”, I like getting “Blue Suede Shoes”, songs by “Blue Rodeo”, the album “Blues Clues Sings the Blues”, songs in the “bluegrass” genre, and anything tagged “songs that Ol’ Blue likes when we’re huntin’” all in one go. So we’re going to use the same approach to all our search screens whenever we can. Since this is a client search screen, and not a general “find this text in this document”, it has some interesting considerations. Firstly, the traditional version of word forms doesn’t apply. For example, searching for “Bob” doesn’t mean I want results that contain “bobs” or “bobbing”. But I might want to get someone named Robert or Bobby. And while it should certainly return Bob Roberts, what about Jodi Roberts? Another issue is misspelled names. As in, how do you know when a name is misspelled? It would be nice if the user entered “Peterson” and it was smart enough to recognize that maybe they meant “Petersen”. Similarly, it would nice if searches for DeWinter brought back Alex De Winter. Come to think about it, how *do* we handle searches for multiple words? Split them up and search individually, collecting the results seems the obvious choice. Related to this is the idea of partial searches. I asked a question on Twitter: Should a client search screen handle partial searches? General consensus is that yes, you should. Problem is that I asked a bunch of developers who are used to Google. The main argument is long, complicated names. If you don’t allow partial matches, woe betide Mr. Nahasapeemapetilon if he decides to call in for an appointment. But I want to capture the intent of The Average User™. For example, if I search for Peters, would I expect to see all the Petersons and Petersens in the results? Or would that be noise? Why would I type out “Peters” if I wanted “Petersons”? To take another example, what if I search for “Ng”. Do I *really* want to see all the Fingoods and Mannings and Hutchingsons and Worthingtons in my search results? Perhaps not, but maybe I’m trying to find Kate Ngwanangwa. First names are kind of an odd field to search for in any case. It’s rare someone would search by first name alone but it would make a good qualifier for a common last name. For example, it would be easier to get a hit on Katharga Smith if you add the first name to your search. So then the question becomes, if someone searches just for Peter, does it include all customers named Peter? What is the intent of such a search? To find William Petersen? Or Peter Ritchie? All of this can be summed up as: it’s hard out here for a hillbilly. Partial searches were a particularly in-depth discussion during our back-of-the-sleeve analysis. My position was to use an exact search and include a link at the bottom “didn’t find what you were looking for? Click here for more results.” This is kind of the IMDb approach where it shows exact matches followed by partial matches. In our case, we wouldn’t show partial matches right away because the IMDb search page makes me feel unhappy to look at. My friend’s position is that eighty percent of the time, people will search by phone number. Of the remaining twenty percent, about 95% of it will be an exact search. E.g. “John Wilkins” or even just “Wilkins”. If the user has trouble finding someone, there’s always the letter list along the side. For the majority case, he feels the traditional approach of showing partial searches, even if they aren’t highlighted, is a user experience fail and just adds unwanted noise. Given the slogan at the top of my blog, he makes a compelling argument. Of course, this isn’t a new problem so we turned to an authoritative source to see how they implemented it, in this case, GMail. Alas, results were mixed. If I search Contacts for John, I get all the Johns and all the Johnsons. But if I search my email for “from:John”, I get all emails from John, my childhood friend, but none from G. Johnson, my plumber. Oddly, the Google suggest that pops up as I’m typing the search criteria *does* show the plumber. There’s also a technical angle to this in that Big Table doesn’t support LIKE clauses so it would be non-trivial to implement partial matches. Not that that should dictate features but it does mean that we should think long and hard about whether it is actually required. In the end, the goal is to capture the user’s intent, at least most of the time. To that end, we’re going with an exact match for now. If you search for William, you’ll get William F. Buckley but not Roberta Williams. Similarly, looking for John Wilkins will get customers with that name, but John Wilkinson will remain anonymous in that case. We feel that this, along with a phone number search (which will likely be far more common), will cover 95% of our needs. This gets us to product delivery faster and for the remaining 5%, the letter list should suffice. So we’re taking a Getting Real approach and waiting until we hear from real live users before putting any further effort in. And as my friend noted, it’s a lot nicer to add a feature in than it is to take it away after people are using it. Kyle the Unfounded
Friday, April 09, 2010
Still heads down in start-up mode with GWT these days, which sounds more glamorous than it is in practice. That said, we’re looking for a junior Java developer and a Web Marketing Assistant so send on your details if you’re interested. I’d suggest reading the rest of this post first though… This week, the progress report to my boss essentially read: The app has now returned to the same state it was at a week ago. But it now uses a new architecture that sure makes me feel all warm and fuzzy. This isn’t as clandestine as I make it out to be. We had a chat on Sunday after I’d spent a few hours prototyping the new architecture and had a brief bout of conscience wondering if switching things so drastically was just a way to satisfy some primal developer itch. I mean, in a company of 10,000 people, it’s easier to justify in many cases. Especially if the company has a tendency to swap out CMS products semi-annually. That, to me, says “we need to spend our budget on something this year or we won’t get it again next year.” But on a project of this scale, architectural changes cost much more relative to the income they generate, which at this stage is nothing. During that chat, I made some estimates on how long it would take to revamp things. Optimistic estimate was two days, pessimistic/realistic one: five days. I hit the pessimistic one more closely than the optimistic one but frankly, I’m just glad the estimate fell in between the two. Based on that, my cohort essentially said it would be stupid not to do it. We are early enough into the project that the long-term payoff will be substantial. Five days of work does indeed sound like it would be easy to make up over the lifetime of the application. But there are other considerations than just plain time. The libraries I was replacing are gwt-dispatch and gwt-presenter. Both relatively proven, actively developed, and by all accounts, very good at what they do. Based on my own limited experience, I was very happy with both. The replacement is gwt-platform, which by contrast, had its first check-in on March 3. When I joined the discussion group, I became member number 9. So there’s some risk involved with such a fundamental shift to a fairly unproven library. Another consideration: although gwt-platform has some nice features to it, there’s a very real possibility that they’ll be implemented in some form in gwt-dispatch and gwt-presenter. And I wasn’t even looking to change. I effectively stumbled on to the library while checking up on Andreas Borglin’s adventures in GWT and he has yet to steer me wrong. So the question remained: do we take the risk of switching to a new library with a more uncertain future for the sake of easing our development now? In the end, we decided yes, we would. Because the risk doesn’t seem all that great, really. It’s an open source project. And not one like NHibernate where if it went belly-up, you’d be scared to navigate the code (and if you’re not, then this post isn’t aimed at you). The product is still fairly small and according to the upcoming features page, plans to stay that way. My partner put it best during our discussion: “don’t be afraid to rip things out and start over if there is real business value.” But as a developer, I’m very much aware of my personal bias so it’s often hard for me to judge “business value”. Especially in this case where I wasn’t altogether unhappy with the existing products and there was an element of “Ooooh, Shiny!” to the decision. The nice thing in this case was that the project is in its infancy and a major upheaval of this sort is only a week’s worth of effort. Not totally insignificant but still within the realm of justifiable spike, even for a start-up. In fact, it’s because we’re a start-up that I think the decision to switch was so easy. Trading uncertain future for present development time? That means “possibility of having to look at code we didn’t write” vs. “saving a trailerful of money”. Besides which, after scanning the library and the corresponding sample project, it includes solutions to quite a few issues I had been ignoring until I had time to revisit them: - Lazy loading presenters
- Code splitting
- Resource (i.e. CSS, images) management
- Internationalization
- Ability to use nested presenters, especially with UI Binder
So between making things easier going forward and solving problems I had not even thought about yet, it certainly warranted an evaluation. And after spending a week with the framework, it has proven itself extremely valuable in crystallizing a number of concepts I was having trouble with. Many kudos to Philippe Beaudoin for his effort in that alone. Kyle the Upheaved
Saturday, April 03, 2010
I hope this post doesn’t come across as contry-vershul as I expect it will. I do have a larger point to make. That said, I take comfort in the fact that I live in a country where laws are seen more as guidelines so I feel somewhat protected against people that will take this the wrong way. Regardless, it’s a meta-post that upon reflection, doesn’t say too much. But it took me &*%$ forever to type it up so off to the Internet it goes! Before we get started, the over-arching theme of this post is priority management, not shit disturbance. But in order to get to it, I’m going to discuss both the MVP program and the book-writing process both of which came to the forefront of my mind recently as new MVPs were announced along with the release of our book (We made it on April Fool’s after all! Woohoo!). Over a year ago, Karl Seguin did a piece on the MVP program, characteristically walking the fine line between rant and debate in a way I’ve only been able to achieve once, at our most recent family reunion where we discussed the finer points of the definition of “same sex marriage”. At the time, I was also a little disenchanted with the program as I felt I wasn’t recognized for what I thought were fairly significant efforts. But reading Karl’s post and letting it sit for a few more nomination cycles has led me to a different perspective. I’ve had conversations over the last year with people who are graciously indignant that I’ve been passed over. We talk of inequities in the system and the grey area of where I live versus where I make my contributions and such. But since reading Karl’s post, the question that keeps coming up in my head is: Why do I want to be an MVP? And lately, that has morphed to: Would I accept it if it were offered? We’ll get back to that but let’s move on to the next topic. Book-writing is hard. It’s not just the work involved but the constant feeling that you should be working on something when you aren’t. It makes you feel guilty when you’re out having a good time with your family when you know you should be getting other stuff done. Then when you’re doing it, you feel guilty because you’re not out having a good time with your family. So the question that kept coming up in my head was: Why do I want to write a book? Why not just write the articles and release it as an ebook? Or a wiki? These two issues made me wonder about my motives. I think it also helps being relatively isolated from the software community as I don’t regularly geek out with anyone locally. Mostly because geeking out down here involves GPS equipment on boats and the hillbilly ain’t what you would call a seafarin’ folk. Without regular reinforcement from peers, the intrinsic value of both activities starts to get a little fuzzy. So I start wondering: what benefit might I gain from being an MVP? Free software, possibly. A half-expenses paid trip to Seattle each year. Possible consulting work. Inside look at new technology coming from Microsoft. Ten years ago, that all sounded pretty good. These days, with the hillbilly closing in on forty, all of that sounds like more ambition than I have the energy for. Free software? Most of it would take up hard-drive space and never get used. Possible consulting work? I reserve the right to reconsider my position on this one if I’m ever out of work for longer than two months. New technology? I can’t even handle current tech. Besides which, all the interesting stuff isn’t in the actual technology anyway but the products that come out of it. Note that I do recognize the similarity between this argument and the Fox and the Grapes fable. And it’s easy to say I wouldn’t accept the award if it were offered. That’s especially true now that I’ve declared so publicly which probably doesn’t bode well for me ever being nominated again. But the fact remains that the further I get into my career, the lower the value I place on the tangible benefits of the MVP program. The recognition that I thought I needed tends to come regardless of what the program dictates. In any case, if I were to get it now and not for the community work I did in 2008, my confidence in the selection process would be shattered. As for book-writing, many of the same arguments apply, at least for the tangible benefits. The traditional arguments about the benefits (e.g. fame, wealth, power) are either just plain false or grossly exaggerated. If I were to release it as a wiki and get a single contract based on that contribution, the financial benefits are negated within one to two months. That said, there are considerable intangible benefits to writing a book depending, once again, on your priorities. A print book does tend to legitimize the ideas within, assuming the book is well-received. As my co-author pointed out early in the process, there is a wider chance that the ideas will reach the people we want to reach if it is published. I think that’s true, as much as we’d like it not to be. And given that assumption, that increased the priority I had for writing the book. This is not to slam the MVP program or its current members. I don’t really have an opinion either way on how valuable the program is because it doesn’t really affect my daily life. Nor is it to dissuade anyone from writing a book (or an ebook or a wiki). Instead, it’s to consider the importance you place on these achievements and by corollary, the priorities you have in your career. Yes, I like to keep the running joke of my Slightly Below Most Valued Professional status going but not out of bitterness or for a personal agenda. I’m just a sucker for the ironic is all. And as much as I complained during the book writing process (mostly internally), I’m very proud of the output from it. Whether or not it sells or gets good reviews, it’s already achieved the goal I set out to do: to make the information available to whomever wants to consume it. And in a way I’m happy with. For instance, one of the things I like most about it is that it ends on the word confidence. And we didn’t even plan that. I really should dump some images in this post to break it up a bit. But it’s not at the top of my priority list right now. Kyle the Prerogatory
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
Copyright © 2010 Kyle Baley. All rights reserved.
|
|
|
CATEGORIES
|
|
LATEST POSTS
POPULAR POSTS
|
|
ARCHIVE
| September, 2010 (3) |
| August, 2010 (1) |
| July, 2010 (3) |
| June, 2010 (3) |
| May, 2010 (1) |
| April, 2010 (5) |
| March, 2010 (4) |
| February, 2010 (8) |
| January, 2010 (2) |
| December, 2009 (3) |
| November, 2009 (2) |
| September, 2009 (5) |
| August, 2009 (4) |
| July, 2009 (2) |
| June, 2009 (5) |
| May, 2009 (6) |
| April, 2009 (5) |
| March, 2009 (6) |
| February, 2009 (2) |
| January, 2009 (6) |
| December, 2008 (5) |
| November, 2008 (2) |
| October, 2008 (5) |
| September, 2008 (9) |
| August, 2008 (5) |
| July, 2008 (7) |
| June, 2008 (6) |
| May, 2008 (11) |
| April, 2008 (13) |
| March, 2008 (13) |
| February, 2008 (12) |
| January, 2008 (19) |
| December, 2007 (16) |
| November, 2007 (8) |
| October, 2007 (23) |
| September, 2007 (15) |
| August, 2007 (8) |
| July, 2007 (6) |
| June, 2007 (11) |
| May, 2007 (19) |
| April, 2007 (14) |
| March, 2007 (3) |
| February, 2007 (4) |
| January, 2007 (7) |
| December, 2006 (5) |
| November, 2006 (9) |
| October, 2006 (11) |
| September, 2006 (14) |
| August, 2006 (11) |
| July, 2006 (15) |
| June, 2006 (8) |
| May, 2006 (10) |
| April, 2006 (12) |
| March, 2006 (3) |
| February, 2006 (7) |
|
|
|