Software architecture cheat sheet
gorban.org
gorban.org
I'm a big fan of #1 being "State the problem." rather than "Is this a 'Good Idea'?" they are inter-related of course, but any good software architect has their eyes fixed on the problem so they don't get distracted by the opportunities to 'decorate'.
I like asking people what they think the 'architect' does, that is to weed out people who think architect implies a leadership role, it can be but it isn't necessarily. In the 'real' world the architect is the person who notices you've got a banquet room for 100 people but the nearest restroom is two floors down, or a single hallway connecting both the people and the kitchen to the room. They see the 'whole' goal (feed large groups of people) and then work out what has to be true for it to be not a problem.
I look for similar skills in software architects, they don't care if the implementation is rails/django/node but they do care that individuals can be identified as users or guests, given capabilities or not, can be disabled or not, and the largest possible number are welcome.
Sometimes architecture is combined with the person who does design, sometimes with the person who does coding, and sometimes its just a person asking really good questions at the launch planning meeting.
There is an entirely different (and very valuable) class of folks to can take an existing screw up and map out a series of steps to un-screw it up [1]. :-)
[1] I used to watch the New Yankee Workshop on PBS and see Norm cut lumber and then have it fit together so closely and smoothly that it practically didn't need glue. I suggested to my wife we could make a TV show which explored creative uses for a 2 x 4 that was 1/2" too short for its original purpose, or other parts that were made scrap by an imprecise execution of the 'cut to size' phase.
http://www.amazon.com/Principles-Software-Development-Alan-D...
If you're using an RDBMS, use it. The model is just a representation of the data's canonical, authoritative state, which is what it looks like when it's been committed to the DB. The only way to keep your data sane is with Foreign Keys enforcing referential integrity between tables, and the only way to do that is to specify the relationship in both your models, and in your migrations.
Blind, slavish adherence to a pithy acronym is just going to get you into trouble.
Then again, there can be valid reasons for repeating yourself when writing code as well. Personally, I prefer "don't repeat yourself without a clear reason for doing so", which is a very different guideline.
No developer who says, "DRY" actually means, "Never, ever repeat yourself." No developer who offers advice of any kind expects that it applies under all circumstances. We still phrase it in strict, prescriptive terms because it retains more of its moral force that way.
Anyone who expects pithy development advice to note exceptions is interpreting it in a juvenile way.
Having been a mentor to many younger and less experienced programmers when they started working professionally, I have been the guy who had to clear up their absolute, literal belief in these sayings. Some people will quickly understand and accept that the world isn't as black and white as perhaps their CS course/favourite blogger/previous boss said or that they have taken rules of thumb too literally. Some never really do understand that, and their code reflects their lack of understanding and often looks like it was written to comply with every saying under the sun as its primary goal.
Sometimes, reaching that ideal is not practical and in the name of pragmatism a programmer will indeed repeat themselves. But that repetition is where the trouble starts. If you have to describe a relationship twice, then sooner or later someone is going to forget to update one place or the other. As a database guy, you would like them to always remember to update the place that tells the database about that relationship. But in reality, it may be just as likely that someone will update the model and forget to update the database.
The idea with DRY is that you should try very hard to find a way to represent the relationship only once so that mistakes can't happen, but that doesn't mean sacrificing the integrity of your data to do so.
That said, I know little about Rails, and perhaps it's hard to do it right, or at least easy to do it wrong.
Adding a database field often has repercussions throughout the stack (not to mention throughout the rest of the system).
What's really interesting is to realize that DRY is traditionally only applied to static code, rather than runtime state. But personally I think it should apply to both.
Its common nomenclature in the scripting and web space, but less so in other areas.
It was called design normalization and factorization when I was introduced to it in the early 80s.
An ironic plight.
I added your comment, I hope it's OK.
It should also include
>Bias: Is this an agnostic solution? Am I or anyone else too invested in it?
Testing, for example, is obviously paramount in architecting buildings because failures can be horribly expensive and lethal ... but software development is too often prone toward "happy path testing".
Repeating is more problematic in software thanks to Ctrl-C / Ctrl-V, whereas other disciplines have nontrivial time & cost sunk in doing something more than once.
Cost of changes is profoundly different. Since building software is nigh unto free (click "build", wait seconds or minutes) instead of costly (bridges take months or years), those involved are too often seduced by the notion that changes cost nothing.
That fact makes the key design principles different. Fully a third of the bullet points on this cheatsheet speak directly to the needs of making that kind of change later.
An architect is more likely, like his building counterpart, to see the system from the top down. That is given a clean sheet of paper: How can we achieve the availablility and fault-tolerance we need? what is the threading model? how does the system connect to the outside world? etc...
Whoever takes the role of doing this makes sure that the direction of the implementation doesn't loose sight of these goals. He may even create non-functional requirements.