On Mon, Apr 24, 2006 at 10:14:09AM +0200, Mischa Peters wrote:
} I am doing some research on how people start with their Rails app.
} What design decisions are made and how is it build.
High-level requirements first, which get clarified and detailed
throughout
subsequent development. This is true even (particularly?) for my own,
personal projects; I write developer notes in the doc directory and keep
them up to date. Data model next, which shakes out a lot of the
ambiguities
in the requirements. This is half personal preference and half
unpleasant
experiences with other approaches. Thereafter…
} For example:
} - do you use scaffolding and go from there? Or do you create
everything
} from scratch?
I found scaffolding instructive when I was learning how to use Rails.
For
nearly any interesting application (i.e. that isn’t just a Web-based
FileMaker app) there is a many-to-many mapping between controllers and
models rather than the one-to-one mapping that scaffolding assumes.
Controllers are about functionality. The data model is there to support
the
desired functionality, but it is not, itself, functionality. The
important
thing here is that controllers sit on top of the data model, rather than
simply exposing it.
} - are you using multiple controllers? Or do you put everything in one?
For the same reasons that we don’t want one big main() function or one
big
object, we don’t want one big controller. The last four or five decades
of
programming have taught us to break problems down into smaller problems
and
solve them modularly. Rails does not change that wisdom.
} - do you use migrate?
Hell, no. I value my data integrity, and regardless of what DHH says I
will
damned well have integrity constraints expressed in and enforced by my
database. Unless and until migrating supports foreign key constraints,
unique constraints, and arbitrary check constraints I will be managing
my
database schema with SQL, thank you.
} - how do you use migrate? Do you call migrate your self or do you use
} the migration file that comes with the generation of the model?
N/A
} - when you use authentication, do you have one authentication
controller
} that you share with multiple apps (if you have multiple apps)?
In some cases, if apps are related enough that they should share
account/authentication then they should probably be a single app with
mostly independent controllers. When you start scaling to lots of
individual apps and it starts looking like a suite of apps with “single
sign-on” then it’s probably time to move to a centralized authentication
mechanism with an independent authentication application accessible to
the
individual apps via web services or something similar.
} - do you keep scalability in mind when building an app? How?
Sort of. The data model is a big part of it. If you can design a good
database schema in (or close to) one of the established normal forms,
you
have a good start. Keep an eye on how many data records you need to
accomplish any given task (read: controller action), and how many
different
tasks modify (reading is less of a concern) the same records. Some rules
of
thumb:
-
Store a bare minimum in the session hash. Particularly, do not store
records, just ids.
-
Make it easy for the client to cache. This means reusing as much as
possible various static resources such as images, JavaScript
libraries,
and stylesheets. Remember that anything you generate probably won’t be
cached on the client, even if it’s cached in Rails.
-
Don’t send anything to the client you don’t have to. Anything you send
probably has to be read from the database, and it definitely has to be
rendered as ERB and sent over the wire.
-
Don’t send redundant data to the client. If you look at the JavaScript
that RJS and the various AJAX helpers produce you will find that it is
pretty redundant. If you find that you are using a lot of it on the
same
page, you might want to push the similar stuff into a JavaScript
library
(see the point about client caching) and write your own helpers that
use
it for your specific purposes.
-
Use Rails’ builtin caching (duh).
} - anything else that you can think of… 
Security is important, and not something that one slaps on later. It’s
an
integral part of the system.
-
Never eval anything that came from the client.
-
Never create records directly from params (despite all the examples to
the contrary).
-
Never use string substitution (e.g. “#{params[:foo]”) with data from
the
client, particularly in model find() calls.
-
Never rely on JavaScript for validation. It’s nice for the user, but
always validate on the server.
-
Never assume that requests are coming from submissions from pages your
app rendered.
Accessibility is important. (This is most relevant for the visually
impaired, but there are implications for certain kinds of physical
impairments as well.) It is also federally mandated for all governmental
websites (in the U.S.). One can also be sued for discrimination if a
site
is not accessible.
-
All image tags should have alternate text (i.e. img tags need a useful
alt attribute). This also happens to be a standard requirement of
modern
HTML, even though nearly all graphical browsers will render img tags
without alt attributes.
-
JavaScript should not be required to use your app. There are
situations
in which this requirement doesn’t make sense (e.g. your app’s central
purpose has to do with graphical manipulation, etc.), but the vast
majority of applications are text-based. There is nothing wrong with
enhancing pages with JavaScript, just so long as they are still usable
without it.
-
In case it isn’t obvious, AJAX is JavaScript so the previous point
applies to it as well.
-
See WCAG 2 Overview | Web Accessibility Initiative (WAI) | W3C for more info.
Here’s the short overview of my development process, in order:
-
requirements (updated and maintained throughout development)
-
data model (schema and models, validation checks in both and
scalability
in mind)
-
functionality (controllers with security and scalability in mind)
-
views (with accessibility and scalability in mind)
I didn’t mention testing since I consider it part of the development
process. Use the framework for unit, functional, and integration tests
that
Rails provides throughout the development process; ideally, by the end
of
development the requirements and sets of tests will be nearly
identically
complete specifications of the system.
} I am interested to see what the different approaches might be.
} Thanx!!
} Mischa
–Greg