mod_bandwidth
Posted at February 2, 2006 03:41 PM - Category: Coding
A little while earlier, I put up the Open Source page on the ASO site. Included with this is a little project I've been working on called mod_bandwidth.
We've been using lighttpd to power the macTV video distribution server since last month. When we switched it over, Asif (the owner) says he's been getting 2-3x the speed from the site as compared to before. The thing has also used a total of 200 CPU minutes for all of January. We're sold.
So, we've been wanting to use lighty for ASOextreme, but it lacked a way to limit domains based on bandwidth used. It can track it using RRD's, but won't actually limit the number of bits sent. So, I decided to dust off my C skills and start coding up a plugin. That was Sunday night. I had it tracking bandwidth and displaying a page with that information in about 4 hours. I had it limiting based on configuration values in about 2 days. Wow, that was fast!
I now need people to break test what I've written. It's almost feature complete. I just need to add a global bandwidth viewing page and tidy up a few things. However, the core functionality is there and tested (to a certain extent). Please, give mod_bandwidth a shot and let me know if you can find any way to break it :)
PGF: The Ease Of Rails In PHP
Posted at December 6, 2005 12:30 PM - Category: Coding
Ruby on Rails is clearly the hottest thing since sliced bread on the web right now. Many people are moving over to the framework as a way to speed up their development and get on this whole Web 2.0 bandwagon. I'll leave the argument that Rails != Web 2.0 for another post, but it should be noted that Rails brings to the table some pretty big coding efficiencies beyond just simply reducing the amount of code. So, what if we applied some of those techniques to PHP instead? I've been using this approach to application coding in my own applications lately, and it's offered some major decreases in code and increases in programming efficiency. I call this framework of coding the PGF: PHP Generic Framework.
Objects are the key to this system. PHP has had them since version 4 in a basic capacity. Rails makes them a ubiquitous part of the system, since everything is an object in Ruby. So, we need to make objects a ubiquitous part of our own PHP framework. To do this, we need to eliminate the use of functions in our code wherever possible. Consider this bit of code:
function show_products() {
$res = db_query( "SELECT * FROM products" );
$products = array();
while( $row = db_fetch_array( $res ) ) {
$products[] = $row;
}
...
As you can see, there's a lot of stuff written in there, and I didn't even get to the juicy part of printing it out. I know it's in bad form to reveal the ending right off the bat, but this is what we want to get to:
class Products extends Module {
function show() {
$this->products = $this->db->get_all( "products" );
}
}
Simple and easy-to-understand. The products come from the contents of the "products" table in the database.
Code this simple normally needs a lot of framework code to back it up. However, there isn't any need to write up 15000 lines of code like Rails. Besides, you don't need all that functionality anyways. What I'm going to show you is a guideline for building your own framework. You can use this as a basis and build up whatever components you need. You can also add to it over time as you build new applications and want to improve your central functionality. Need a database abstraction layer for PostgreSQL? Throw that in. Want an FTP access object? Work that into the mix. What I'll show you here is extensible for whatever your needs are, since it only provides a base way of doing things and minimal code on it's own. It's called a generic framework for a reason! Anyhoo, on to the show...
Comments (12) | TrackBacks (0)
How To Make Your Web Apps Suck Less
Posted at November 14, 2005 11:22 AM - Category: Coding
It's been a while since I've written a decent post in this blog, so here's my attempt to make up for lost time.
Frankly, I'm more than a little bit shocked at how bad some web applications are. I don't know if these people are blind, retarded, or both, but there are some truely awful apps being passed off as stable, final versions. Of course, that's how it goes with most anything. There are always those low quality products that make you wonder if there was an open can of paint in the room while they were being designed.
But that doesn't mean you have to.
So, here are some notes on how you can improve you applications significantly. This isn't a complete list, nor is it guaranteed to be accurate. But I think at least following some of the bare minimum guidelines can make a big impact on your app.
Make It Easy To Install
Installers are the biggest gripe I have with just about every web app out there. The majority of them either rely on some separate file you have to edit or are just a form to enter in database details and run some SQL statements. They are generally either the last thing to be set up or are quickly created so the developer can get their script tested and out the door faster. However, that's missing one big thing: Installers are the first thing your users see! You've got to give them as much attention as your application itself. If you don't do that, you start people off with a sour taste in their mouth, and that just sets you up for disaster.
One of the biggest things is making sure there is clear documentation on what's going on. Most people with problems installing scripts don't fully understand the fields they're expected to enter. "What the hell is a 'Database Server Address'?" would be a prime example of a question they may ask themselves. Instead, use lots of descriptive text all over the place. Even if your installer is nothing more than a glorified set of SQL statements, giving a user a better idea of what's going on will ensure less errors and make them feel more in control of the whole process.
Less Bloat
The bloat I'm referring to isn't just large page sizes, it's also in the number of listed features and available options for users. Take a look at a demo of Modernbill to see what I'm talking about. On the main dashboard page, there are 48 images, CSS, and JavaScript files that need to be loaded. In addition, there's a horrid rollover menu at the top, that hides sub-sections until you rollover them, and there are dozens of possible links to click depending on where you need to go in the application. So, what we have here is information overload both in terms of what your computer and network have to handle, and what your brain has to handle.
Now, cutting down on bloat doesn't have to mean cutting down on what your app is capable of. Less features do not mean less capabilities. The point is to make the features you have more flexible and usable so that your users can do more with less. Going back to ModernBill for an example, there's the ability to do an upgrade or downgrade of a user's accounts via a separate wizard interface linked from the client's information screen. This automatically does all the pro-rated billing and sets up things to be upgraded on the server. Instead, why not use the existing screen to edit an account's details. Have it prompt you to pro-rate the cost when you save changes (if the plan has been switched). No new screen needs to be added, you're just using the existing functionality. Hell, if you want to use AJAX, just have the listings of accounts include clickable items that drop down to a selection of possible new plans. Then just pop up a message with any feedback or information that's needed and you don't even need a separate editor screen.
Flickr is a great example of how bloat can be reduced in an app. On the same page you view a photo on, as an owner you can edit the title, description, tags, notes, and sets the photo belongs to. This is all done without an additional screen or interface. So, there are less places to go, but the same capabilities. The AJAX used in this case isn't about reducing reloads, it's about reducing the places you need to go to get things done.
Do The Thinking For Your User
Let's face it: Users can act really dumb sometimes. However, this often isn't because the user is actually stupid, but because they are put into a confusing situation. So, it's up to our apps to fill in that gap and be smart on the user's behalf.
There are two ways to make actions in the system go more smoothly: 1) Instruct the user carefully or 2) Do it for them. The first involves either writing a good manual or providing sufficient contextual help throughout your application. To be honest, it should be both. Many people, myself included, don't like help text all over the place after we've used the application for a while and end up turning it off. So, for those of us like that, you should have a well-written manual available to reference. Seriously, writing a manual should be as important as writing code. The manual should even be longer than your code (unless you're really verbose with your code...).
As for doing things for the user, I don't necessarily mean full automation, just little nudges where the user needs it. One thing that most coders don't think about is the default value for form inputs. Often time it's left blank and the user figures out what to enter based on the title next to that field. Instead, if we pre-fill that field with information we can do one of two things: show the user how to format input into that field or fill in data they were going to enter anyways. In either case, you boost productivity because you're either avoiding errors in the form or just filling it out for them. For instance, say you have an admin section to enter in items into an inventory app. You could fill a date with "mm/dd/yyyy" (which disappears when you click on the field) to give the correct format and help new users. Over time, your application can determine the best pre-filled value for that field and enter it in each time (most likely it would be the current date).
The End
That's all I've been able to think of off the top of my head. If you have any other suggestions for areas I should comment on, feel free to leave them in the comments. Again, I'm not any form of expert, I just play one on TV. I'm sure I've made errors (both logical and grammatical), so feel free to point them out. If there's enough interest, I'll post up a followup on this to clarify anything that needs it.
Anyways, get to it! Let's see some killer apps!
Skidding On Rails
Posted at October 10, 2005 01:35 AM - Category: Coding
So, I've been looking around for some sort of employee time tracking system to use at ASO. And naturally, everything out there just seems to suck. My options are either ugly Windows apps or ugly web-based apps. Neither of which offer anything excellent and all of which are overpriced.
So, I looked at making my own. Given that I've been itching to really sit down with Rails and give it a full-blown try, I chose it as my framework for the app. I've already read through and understand a good amount of Ruby syntax, Rails' API, and how everything works together. When you're running a hosting service that supports Rails, you sort of have to. I'm definitely no expert, but I'm not supposed to fumbling around either.
However, I was fumbling around with Rails. I hit an initial snag that obviously wasn't anything to do with Rails (the Ruby-MySQL interface I had installed wasn't able to login to the server and needed two commands to fix). But after that, I didn't really feel like I was getting any benefit from using this framework. Ruby is a terrific language, so I don't feel like it was a syntactical issue. Rails claims less code and increased productivity. Instead, I felt as though I was getting no benefit whatsoever, on top of having to maintain the knowledge of a separate language and API.
Of course the big question is: why? Why was I not feeling any improvement or benefit? Where did the magic go? I've since realized what it is: Rails forces a design model on you. The one sort of model that Rails uses as a base is MVC, and that's a very good thing, but it then combines in CRUD on top of that. So, what happens is you are sort of forced into thinking about your application in the way Rails thinks. You must think of your application in terms of objects and data models, controllers and views, etc. And for many, that can work out quite well with the application they are designing, but I also feel it restricts how you have to think about your application.
The time tracking software I started doesn't really follow the CRUD model too well. You're not deleting anything or doing any creation except for logging. It's basically just R and U. It also didn't jive too well with the MVC model, as I need to do some lower-level SQL to accomplish a good 3NF database layout. Thinking about showing an employee status page had to make me convolute the Rails model to fit what I was doing. So, Rails implicitly imposed a design model on my application and that hurt my ability to design my software, thereby reducing my productivity as I tried to force things to work.
Now, I know what you're probably thinking is "You're just not thinking about it the right way. I'm sure there's a clever solution." And that would be nice, but it's not really the intent of Rails. It's meant to be easy-to-use with "more joy", but instead I became frustrated with it. My only option was to really just strip Rails down to a simpler controller-view model, which removes almost all of its proposed benefits.
Your next question should then be "What else is there to use, then?". Well, as I've written about before, I've already got the stripped-down form of Rails in PHP form (which I've improved on since that post). I don't have a full API, but I also don't really need it. What I've got is really just a layer over an object in PHP. You can execute a function and define a view template without having to write up extra code on top of that. It may not get the "joy" Rails claims, but it does get the "less code" part.
Now, don't get me wrong, Rails can be a real time-saver and beneficial framework, but I don't see it as being the swiss army knife that a lot of people think it is. I just worry that people read all the marketing and promotion surrounding it, take it as being true, and get stuck using something that may not be the best tool for their job. For me, Rails isn't it.
Plug It In
Posted at August 15, 2005 04:22 PM - Category: Coding
The other day I found this neat little tool called MyGuestmap. To sum it up, it's basically a guestbook and Google Map rolled into one. Provided with a lot of users, you get something like Neowin's guestmap(Warning: It's a little slow to load with all the people we have).
While the implementation is simple (actually, really simple), it's a cool concept that shows the power of build extensible applications. Google Maps has an API they've built to allow developers to make use of the mapping service in their own applications or websites. Google Maps itself is relatively simple tool, but it serves as a great basis for other applications built on top of it.
This is the sort of stance I'm trying to take with ASObill. I can only dream up so many cool uses of the application, but if I give access for others to put in their own code on top of that, all sorts of neat things could be built up. Modularity and extensibility are the key parts of this goal. I'm making as much as I can either a module or plugin to the overall system. This is sort of a given with the sheer number of payment processing systems, server control panels, and other external ASPs we need to support, but it's also about going beyond just that. Inter-plugin support is something I'm going to be concentrating on.
Let me give a real world example for this: In addition to our reseller hosting accounts, ASO is going to offer some sort of discounted or free copy of ASObill with the price. So, when processing the order, it would be ideal if we could have a plugin that will create the account, one that will add the reseller account, and one that will install a copy of ASObill (a mini-Fantastico, if you will). So, I have one plugin for the main hosting account purchase and two addon plugins for the reseller access and the ASObill purchase. There's a whole lot of logic that goes into that. Discounts have to be accounted for. Addons have to detect other addons and the main purchase plugin. That sort of thing.
This is kind of why I really like coding ASObill and really hate coding ASObill. It's interesting but confusing as heck at times.
AIM Fight Widget
Posted at July 22, 2005 06:51 PM - Category: Coding
So, I heard about this neat site called AIM Fight. To summarize, it takes the AOL/AIM screenname of you and friend, and "battles" the two based on your "popularity". Your popularity is determined algorithmically, based on the number of buddies you have, the buddies of your buddies (up to 3 levels deep), and who's online in that big old tree of people. So, not only is it computing the number of people in a large tree of individuals, it's also doing so in real time. Neat!
Someone over at SlashDot had posted the URL that the Flash animation accesses to pull this date. That got me to thinking: What could I use this information in? Why, a Dashboard widget, of course!
Now, I've never coded a widget before this. However, I understood that they were just mini webpages that relied on a little Javascript magic to work. So, I set out on getting one written. I browsed over Apple's documentation and had an AIM Fight widget whipped up in about an hour. Basically, if you're familiar enough with HTML and Javascript, widgets are an absolute snap to code.
So, I present the first AIM Fight widget for download. Simply enter your screen name in the search box and it will show your score. The score updates every 5 seconds while Dashboard is open, so you can monitor your level as people sign on and offline.
Download: AIM Fight Widget 1.0.1
Apple suggests the following information be posted with widget downloads, so here we go:
Mac OS X 10.4 Tiger is required. If you’re using Safari, click the download link. When the widget download is complete, show Dashboard, click the Plus sign to display the Widget Bar and click the widget’s icon in the Widget Bar to open it. If you’re using a browser other than Safari, click the download link. When the widget download is complete, unarchive it and place it in /Library/Widgets/ in your home folder. show Dashboard, click the Plus sign to display the Widget Bar and click the widget’s icon in the Widget Bar to open it
Update:
Man, Apple works late on fridays...
Update 2:
Per Justin's comments below, I've changed the wording "rank" to "score" in the widget display. It still needs support for ranked users (oh, you're not that popular?) with some sort of glowing awesomeness.
Comments (10) | TrackBacks (2)








