Showing posts with label automation. Show all posts
Showing posts with label automation. Show all posts

Wednesday, 19 February 2014

Going Forward; Avoiding the Cliff While Looking for Cliff's Notes

Over on the Ruby sub-Reddit, I got into a discussion (mostly with Jelly_Jim, the OP, and with realnti) about the conflation in far too many minds of Ruby, the programming language, with Ruby on Rails, the famously-"opinionated" Web application framework. While pontificating on Jelly_Jim's original question, I described my frustration-bordering-on-antipathy with the traditional (known as "The Rails Way") application structure; listed a few presentations, books and blog posts that have influenced me greatly, and described my own take on the Kübler-Ross model for Ruby-based (and at least initially, largely Rails-based) Web development.

That discussion, over the course of roughly a day, helped me figure out how our app is going to survive the expected Slashdot effect, transitioning from a pretty traditional, megalithic Rails app to an app that uses Rails components in a sharply different, more recognisably "object-oriented", service-based architecture.

Leaving aside my more prosaic experiential difficulties with Rails (I really loathe ActiveRecord as commonly used), and taking into account the "Uncle" Bob Martin keynote, the various blog posts I referenced in the original Reddit post, and a couple of books I mentioned in a later reply, I think I've possibly hit upon a way to get where I want us to go.

That's the easy part, of course; it only took me never-mind-how-many months. The "interesting" part is going to be getting there — understaffed, on a shoestring budget for the moment even by startup standards (another problem I'm working), and working a schedule for two and a half years that would land a healthy twenty-year-old in hospital by now. Comments/suggestions are, as always, greatly appreciated.


Basic Architectural Principles

  • Loosely-coupled, granular architecture FTW. That means, inter alia,
    • Nearly the entire app to be packaged as Gems used by an otherwise minimal application;
    • Rails mountable engines to package assets (particularly CoffeeScript/JavaScript) and major components;
    • Plan and design for updating and provisioning components which communicate across natural architectural seams.
  • Hexagonal, "ports-and-adapters", or "clean" conceptual architecture; all dependencies point inward. Your domain entities, at the centre of the system, will change less than details like the delivery mechanism (Web UI, phone app, etc) or the database (which the domain shouldn't even be able to prove exists as such).
  • By adopting a heavily job-story-oriented view of the workflows; with the use of online tools like Trello, WebSequenceDiagrams.com; and with supporting code tools like ActiveInteraction and so on, we should be a lot more productive and a lot more Agile than we have been during our forty (calendar time: two) years lost in the wilderness.
  • And oh, yeah, just to keep things interesting: we've got to keep regularly demonstrating forward user-visible progress, for all the obvious reasons and a couple I really can't go into here.

How We Get There, v. 28.0

First, since the major focus of late has been on some unique (and not-so-unique) CoffeeScript code, start there. Separate the existing Script code out into four engine-based Gems, following/adapting Derek Prior's example. These levels are, from conceptual bottom to top:

  1. A "gateway" CoffeeScript class we've written as a poor man's RequireJS, that gives us just enough pseudo-dynamic referencing of data/code without changing anything the Rails asset pipeline assumes;
  2. Our directly DOM-aware Script code, as one or possibly two Gems (one is a major crown jewel; we might decide to split off utility/support code into a separate Gem, so as not to touch one when maintaining the other);
  3. The code proxying our internally-used message queue (decoupling "FTW", remember?) and the Ajax code to communicate with the Rails back end; and
  4. The code implementing various domain/service objects sitting atop the Script stack; one Gem per service.

Next, adapt the relatively-straightforward (as yet) Ruby/Rails code to honour the architectural principles listed earlier. This is where tools like ActiveInteraction pull their weight (and solve several existing pain points in the process).

Just to make sure we really do understand where we're going with this, take our first user story-specific code (including interactor) and package it up as a Gem that should then Just Work as in the previous step. Start thinking about whether we really want traditionally-packaged Gems or unbuilt dependencies that remain part of the single app repository.

Proceed to reimplement and repackage the (again, relatively few) job stories already existing as was done in the preceding step.

Start knocking down the remaining Trello cards as we complete our app.

We've been saying since the Very Beginning that anything that we were building that wasn't inextricably tied to proprietary, commercially-valuable code (or that gives too much of a hint into any unique details it may have) "should be" openly released, but hadn't yet figured out a feasible, cleanly reusable way to do that. If we've done our jobs properly up to this point, we have that way now.

Push the "deploy and launch" Big Green Button. We've bloody well earned it by now.


Any Suggestions or Comments?

Thursday, 18 August 2011

The Yak Shavery; J. Dickey, Proprietor

Starting a new project for a new client, coming up to speed on a bit of kit almost like something I poked around with a ways back, and a ferociously Singaporean flu do not make for a productive week. I'm almost back to where I expected to be by noon on Monday. Since it's noon on Thursday

What I'm trying to learn and leverage is Chef, an automated-configuration tool for computer systems (mostly servers). If you want to be able to reliably, repeatably set up a server (or a server farm), Chef or one of several available alternatives, will make your life much easier. Once you get your tool of choice working, that is.

Step One is, as various Chef amateur tutorials suggest, to start out with a plain-vanilla installation of your OS (Linux, in this case) of choice. Rather obviously, getting from bare metal (or bare VM disk platters, if you'd rather) to the basic working system should be push-button automatic as well. "Fine," you say, "nearly every major distro has its own automation system; surely I should be able to just pick up, say, a Red Hat Enterprise Linux clone like CentOS or Scientific Linux and use a Kickstart file, and it should Just Work. Right?"

Close; but then, "close" only counts for scoring purposes in horseshoes and (arguably) the use of hand grenades. This is neither, though it does have the ability to blow up in our faces with unpleasant consequences.

Putting together a basic Kickstart file to set up a base system (on which we can use Chef to complete installation and configuration; the whole point, remember) is itself pretty straightforward. Except for one "little" thing:

A rather scary dialog
(not my actual screenshot; this one courtesy of Máirín Duffy.)

Hitting the "Reinitialize All" button will allow the install to finish as expected, but it's still a manual action in a process that's trying to eliminate such.

Some bit of Google-fu later and asking questions on the #centos channel of irc.freenode.net (thanks, Wolfie!) pointed me to the correct option to set when clearing the disk partitions, and all should have been peachy-keen and wonderful from that point on. Except it wasn't, of course.

Tests conducted with two different versions each of three RHEL clones on my VMWare Fusion 3.1.3 system all failed with a mysterious "cannot read repodata" fatal error being thrown by the installer.

Except, of course, that mounting the DVDs in question and browsing them showed the /repodata directory and contents exactly as they should be. Fast-forward through a day of flailing and fuzzing different options "just to see what happens", and you have a classic yak shave.

So, knowing that I'll have to get the RHEL versions working eventually, and having been previously warned against using Chef-on-Ubuntu as a learning exercise, I'm now spinning up AutoYAST on openSUSE, which is (experientially) what I should have started with from the beginning.

The wall, where my head has banged against it repeatedly, can be repaired. The calendar? Time is the ultimate non-renewable resource.

(Anybody who has any suggestions for Making This Work with RHEL clones, ideally Scientific 6.1 and/or CentOS 6: enlightenment would be Greatly Appreciated.)