My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
This one refers to the 40+ minute presentation by Obie Fernandez on Agile DSL Development in Ruby. (Is InfoQ not one of the greatest resources ever?)

You should really view the video for better details, but I'll give a little rundown of the talk here. Obie starts out talking about how you should design the language first with the domain expert, constantly refining it until it is good - and only then should you worry about implementing it (this is about the same procedure you'd follow if you were building an expert system as well). That's where most of the Agility comes into play. More...

Hey! Why don't you make your life easier and subscribe to the full post or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!

It's been a couple of months, but cfrails has been "officially" updated (as in, I released a new zip, not just put new code into the repository).

We're a lot closer to 1.0 than one quarter of the way, so soon you should be seeing higher version number jumps. Anyway, here's what's been updated with this release: More...

Something I haven't thought much about, but am beginning to (want to) get into is the auto-generation of reports. Autogenerating forms, validation, and operations for CRUD is quite simple - the approach I've used simply gets what metadata it can from the database, and dynamically builds around it. So, NOT NULL fields become required, datetimes build different form fields from nvarchars, and validate as such (as do other types), and field maxlengths are honored on the HTML side based on the DB metadata (among other things). That is incredibly useful by itself, but not useful enough for a real, production quality application (should the user really be required to remember the categoryID?) More...

As I'm getting into little details about the generation cfrails is doing, I had a couple of questions I thought the community could provide some insight on better than my own experiences regarding lists.

One of the great things about generating this stuff is that you can have for free all the bells and whistles that used to take a long time to do. In particular, you can have sorting on columns automatically generated, as well as pagination.

So question 1 is: given that you can have sorting for free, would you rather automatically sort on every column, and specify any columns you did not want to sort on, or would you prefer to not have sorting placed automatically, but just specify which columns to sort on?

And question 2: Given that more and more people are on broadband, is it time to up the 10-record limit on results? I find it annoying to have to reload all the time, and if given the option, I normally up the results/page to 50 or 100. What do you think, would you make the default number of results/page higher (and how high would you take it?), or would you cater to the lowest common denominator?

There are a couple of drawbacks (or some incompleteness) to scaffolding being truly useful. The one that seems to be most often cited is that normally (at least in Ruby on Rails, which seems to have popularized it) it looks like crap (it is only scaffolding though). Of course, most who make that complaint also recognize that it is only a starting point from which you should build.

Django has been generating (what I feel is) production-quality "admin" scaffolding since I first heard about it. It looks clean and professional. Compare that to the bare-bones you get by default in Rails, and you're left wondering, "why didn't they do that?" Well, as it happens, it has been done. In particular, there are at least 4 such products for use with Rails: Rails AutoAdmin (which professes to be "heavily inspired by the Django administration system"), ActiveScaffold (which is just entering RC2 status), Hobo, and Streamlined (whose site is down for me at the moment). More...

Back in December, I had a post about why closures are useful. In particular, I mentioned what I called the "generalized Template Method" pattern as a benefit: basically, you have a function where, when the user calls it, you want them to be able to change its behavior in some way.

I was short of practical examples, but today I came across one. I've got a list() function that behaves identically for each object it is called on. Basically, it figures out what properties the object has that should be listed, and creates a table that lists them for some query result set. Normally, this just outputs the variable's value on a cell with a white background. The slight change in this case was that depending on the value, the list should set a background color to one particular cell. More...

This morning has been strange. On the drive to work, I started out thinking about encapsulation, and how much I hate the thought of generating a bunch of getAttribute() methods for components that extend cfrails.Model (in cfrails, of course). To top it off, I don't know how I'd generate these methods other than to write them to a file and then cfinclude it. But as I said, I really hate the idea of (say in the views) having to write code like #person.getSocialSecurityNumber()#. That's just ugly.

But then again, I don't like the alternative of leaving them public in the this scope either, because then there is no method to override if you wanted to get or set based on some calculations (of course, you could provide your own, but you'd have to remember to use them, and the attributes themselves would remain public. Currently, this is the way its done, because I feel like providing default getters and setters is not really encapsulating anything on its own. The encapsulation part only enters the game when you are hiding some implementation of how they are calculated or set. More...

One of the great benefits of using a framework (in the general sense) is the freedom in portability it often gives you. Rather than writing your own Ajax routines which would need to handle browser incompatibilities, you can rely on Prototype/Scriptaculous, AjaxCFC, Spry, or a seemingly infinite number of Ajax frameworks available. We see the same phenomenon in our use of ColdFusion, which uses Java to be cross-platform. And, you can get the benefit for databases by using a framework like Transfer or Reactor or ActiveRecord in Ruby (all also have a slew of other benefits). In general, we're simply seeing an abstracting away of the differences between low-level things so we can think at a much higher level than "oh crap, what if they're using Lynx!" (Ok, I'm doubting any of those Ajax frameworks fully support Lynx =), but you get the picture) More...

A thought occurred to me today- just because something doesn't offer all you need, doesn't mean you can't put it to good reuse. This goes back to Sean Corfield's post about why you should avoid the not-invented-here syndrome, my own post about why I thought I would release cfrails (and some of the decisions therein), and a multitude of others who realize that reinventing the wheel is not generally productive.

I had the realization today (though, I must admit it is quite obvious!) that there would be nothing wrong with adding an extra layer of abstraction, which would in turn add the features you needed to some other product/library/code. So when I thought "well, I can't use Transfer or Reactor" (what ever happened to Arf!?) because they didn't provide all the metadata I needed, I could have still built on top of them. I guess the thought never occurred to me back then.

In any case, it has now. Although I'm far enough along that I don't think doing this will save me any more time, it's something I plan on investigating- at the very least, it could provide a familiar API to use (and of course, the framework would be generating any XML files rather than having the programmer modify them).

So basically, if you think you don't want to use a pre-made product - at least you should look into the possibility of building on top of it.

Just a quick note - thanks to help and some pointers from Dan Lancelot (I'm so tempted to write "Sir" - but will refrain for the time being =)), I've updated the cfrails distribution and repository over at RIAForge with a couple of bug fixes - one in particular a big one that made a liar out of me (I had forgotten to update the app_skeleton with the latest router).

Thanks Dan!

Just a quick note: the online class/method documentation for cfrails has been updated to include most of the available methods. All that is missing are the function aliases between functionName and function_name are missing, since that isn't generated automatically. If you happen to be using it and notice that one function isn't available either way, be sure to let me know.

It's been a while, but I'm glad to have that off my to-do list. You can find the cfrails docs here.

Sean Corfield's post about the perils of NIH and RTW and Peter Bell's subsequent one entitled Should you Release Your Framework? got me thinking about my own decision to release cfrails.

Sean mentioned that the not-invented here syndrome, along with reinventing the wheel, "plagues any coherent attempt at Open Source within the ColdFusion community - look at the number of half-baked calendars available (and don't get me started on the unit testing frameworks!)." I wanted to add, "and look at all the generation going on!" (as I can think of at least 5 such projects off the top of my head, my own being one of them.

In general, NIH and RTW are bad things. And Sean is right, to a degree. But I also agree with the sentiment of Peter's post: more is better but if it is substantially similar to another project, it may be better to contribute to that one instead. More...

I can't remember the last time I used anything resembling a stack or queue (other than what I'm about to blog about). Of course, I've used lists and arrays, but not with the same intent you often see in the use of a typical LIFO or FIFO mechanism. I did have occasion to use the concept in the last couple of updates to cfrails, however, so I thought I'd bring it up in case anyone else came across the same use as I have. Let me explain how I arrived at the need (which also doubles as a little documentation):

Using cfrails, to make a model you simply go into your project and create a CFC that extends cfrails.model in the model folder. Assuming that file has the same name as a table in your database, you've now got an object (after it is instantiated, of course) with all the basic CRUD methods. The case is similar for the view or controller, where you'd be in the appropriate directory, but name it modelname_view.cfc or modelname_controller.cfc. There is a way to change the name of the table if you don't want the model name to match the table for some reason, but I'll not go over it here, as it's an "undocumented feature" at the moment. More...

If you're not familiar with what cfrails is, it is a somewhat new framework (I started it in November 2006) for building applications in ColdFusion. It does things like saving records, getting records, populating forms, and data validation automatically for you. It also provides nice abstractions for those things which it can't automatically do based on the database metadata (for instance, you may want a month/year date field, rather than a full date). Since I don't want to take too much of your time describing it, more info on it can be found on this blog post about cfrails 0.2.0 or at the cfrails RIAForge project page.

This update is a super-minor version change, but a significant one.

First, a couple of minor items - I added some more aliases to have functions read better. For instance, instead of doing set_title_new() to change the default title on a view's new item form, you can now write newform.set_title(). Similar additions were made to the record listing table and edit forms. There will probably be other small aliases as well, as I discover more awkward function names. Some of those old ones will go away, but I'll keep the ones that aren't awkward. Just as well, I also made a few more aliases of the type camelCaseFunction = camel_case_function, to allow everyone to keep their respective programming styles. However, if you are naming arguments, you're currently at the mercy of whatever I have called them. I plan to standardize soon - its just weird thinking in Ruby and programming in CF - I'm mixing styles a lot. More...

When I wrote that PseudoObject.cfc would be useless, I was thinking that all objects created would need 3 file operations, and thus, it would be quite unlikely to perform any better (or even on par with) normal object creation.

Based on the way I implemented it in that post, it would need three file operations.

But sitting in my data management class today, I was reminded of ORM because the professor noted that we wouldn't normally think of methods acting on an entity in the database, while each entity would have every other thing we would find in a typical object.

In any case, I realized you could move the file operations out a bit, and they would only need to be run once if you were building a ton of objects that shared the same type. This, I would think would be a substantial improvement over creating tons of real objects. And where would you do that? In an ORM framework - if you wanted to return an array of structs as objects. Then, each could be manipulated as if they were a real object!

Now, it would be freakin' sweet if you can attach a function to each row of the query like this. I expect it would be straight forward if possible, but if not, we can still see a lot of possibilities for ORMs out there (I'll probably test that tomorrow). I plan to implement something along these lines in cfrails, if it does hold up for thousands of objects.

(and functions with arguments can take more than the defined amount)

This may be well known, but I haven't seen a lot (or anything) on it. Of course, as always, I may just be missing something.

In any case, the other day as I was looking over some old code, I (re)discovered this marvelous fact. Now, you may be wondering why on Earth I'd want to use arguments in a function where none were defined. But, I have at least one case where I think it's valuable: suppose you are following the Active Record Pattern, or really writing any ORM. Basically, you want to abstract the query process. Now, that's certainly a noble goal. But, what happens when you want to provide a filter? For instance, you might have a function find_by_id(), a which finds a record based on the id you pass in. That's easy enough. You might even provide methods to find_by_other_columns_even_in_combinations(). More...

For those that don't know, cfrails is supposed to be a very light framework for obtaining MVC architecture with little to no effort (aside from putting custom methods where they belong). It works such that any changes to your database tables are reflected immediately throughout the application.

For instance, if you change the order of the columns, the order of those fields in the form is changed. If you change the name of a column or it's data type, the labels for those form fields are changed, and the validations for that column are also changed, along with the format in which it is displayed (for example, a money field displays with the local currency, datetime in the local format, and so forth). I've also been developing a sort-of DSL for it, so configuration can be performed quite easily programmatically (not just through the database), and you can follow DRY to the extreme. Further, some of this includes (and will include) custom data types (right now, there are only a couple of custom data types based on default data types). More...

InfoQ has an interview with Ryan "zenspider" Davis, a "hardcore Ruby hacker." The interview covers several topics, but those of interest to me and the stuff I've been working on lately with cfrails include DSLs and metaprogramming. It doesn't give too much of an in-depth treatment of these topics, as it's only an interview, but I found it interesting so I thought I'd link it.

Two of the 3 projects I'm working on right now will be built using cfrails for at least some of the development. The third has such a strange architecture that I've never worked with before as to make it hard to see how I might integrate cfrails with it (it's already in version 1, and we've picked it up for version 2 and 3). With the other two, I've already integrated it, and it's quite simple to do.

Therefore, I thought I'd provide some insight in case someone else needed to do it. Both applications are already well established, but we're basically building new subapplications for them, and I've already integrated it for use with single-table manager mini-apps.

Basically, instead of using the provided index.cfm, which routes all the requests, we've already got index.cfms which are used. Now, two options are available here: either use the cfrails index.cfm, and "include" the old one where it says to include the default page, or just change the name of the cfrails index.cfm entirely.

To avoid any potential trouble, I just changed the name. So, now I have cfrails.cfm, where any links that point to actions that cfrails takes care of should go to. So, instead of having index.cfm/controller/action, you'll have cfrails.cfm/controller/action. More...

After my first couple of trial runs, I was a bit disappointed with the performance of cfrails. It was taking several seconds for simple pages to load, which is completely unacceptable. Of course with everything dynamically synthesized for you, you expect a performance hit, because CF isn't all that fast itself, but several seconds is way too long to wait.

After the disappointment, I tried running it on our production box, and while you could still notice it was a bit slow, it wasn't unacceptable. But, if possible, I want to improve the performance (and I have quite a few ideas on how to acheive that).

So, that brings me to the good news: After about a 3-4 month hiatus on doing anything in Coldfusion (except for the occassional maintenance, for not more than an hour at a time), I'm finally working in a few CF projects again (3, to be exact). Working in CF again cascades the good news to cfrails - our development machine sucks. More...

A common problem I've been having and seeing lately is dealing with components that should read files in locations they don't know about. For instance, you have component Model in cfrails, which should read a configuration file in the project that is using it. I didn't want to have to create a mapping for every project, and I didn't want to have to figure out the ../../../../etc between the two directories to pass the value in to Model. So, here's a function which takes care of the mapping for you. If you needed, it would be trivially easy to add a new parameter for base template, if you didn't want to use the actual base template as your basis for inclusion.

It doesn't have any associated automated tests, mainly because I can't figure out how I'd test something like this. So, I tested it manually in 3 different directory structures, and it works fine for me. If you ever find a need for this, and encounter problems, I'd like to know about it - especially the directory structures your using so I can replicate and fix it.

So, without further ado, here's the code:


So, the last couple of weeks I've been hard at work with school stuff, and also we've started a new (well, massively adding on to an existing one) project at work (and now another new one, as of last Wednesday). Because I seem to be so incredibly busy, and the projects need to be done "yesterday" (don't they all?), I built myself a little helper application that should increase my velocity by a ton - no more repetitive busy-work (well, it is greatly reduced anyway).

I've quite unimaginatively called it cfrails, since it was inspired by Ruby on Rails, and you can find it's project page at RIA Forge.

But first, you might want to read Getting Started with cfrails, so you can see how easily 0 lines of real code can create an interface to your database (the only lines are a couple of setup things, and cfcomponent creation).

I'd like to know what you think, so please leave a comment.


Picture of me

.NET (19)
AI/Machine Learning (14)
Answers To 100 Interview Questions (10)
Bioinformatics (2)
Business (1)
C and Cplusplus (6)
cfrails (22)
ColdFusion (78)
Customer Relations (15)
Databases (3)
DRY (18)
DSLs (11)
Future Tech (5)
Games (5)
Groovy/Grails (8)
Hardware (1)
IDEs (9)
Java (38)
JavaScript (4)
Linux (2)
Lisp (1)
Mac OS (4)
Management (15)
MediaServerX (1)
Miscellany (76)
OOAD (37)
Productivity (11)
Programming (168)
Programming Quotables (9)
Rails (31)
Ruby (67)
Save Your Job (58)
scriptaGulous (4)
Software Development Process (23)
TDD (41)
TDDing xorblog (6)
Tools (5)
Web Development (8)
Windows (1)
With (1)
YAGNI (10)

Agile Manifesto & Principles
Principles Of OOD
Ruby on Rails

RSS 2.0: Full Post | Short Blurb
Subscribe by email:

Delivered by FeedBurner