Author Archives: jon

Do I Still Do Domain Modeling?

Got a very nice “blast from the past” contact (4 levels deep) on LinkedIn. Scott was a member of a team where we went through object modeling for their business application.

The reason I wanted to contact you was two fold:

First for some reason that training has stuck with me more that many trainings and I still go back to the cobweb section of my brain and bring it out every time I have a object modeling task, so thanks you did a good job helping me.  This is true for many of the people that were there.

Second as I have been given another task of modeling a large system from scratch I was wondering  about how you feel about the Domain-Neutral model that was presented in the training you did for us.  I have found it useful over the years but do you still use this model in anything that you design this many years in the future?

Thanks for the help.
Regards,Scott

And yes, I still do domain modeling the basic way that we did 11 years ago (gulp). I only have my old copy of Together anymore, so I am stuck back in time there. In person, I always use post-it notes, flip-charts, and markers. Once I want to make a computer version, I’ll use different tools for modeling depending on the need. For example, UMLet is a great little simple tool to bang out a quick diagram in no time flat and that can be used by anybody.

Another good approach from what we went through 10 years ago, is to follow the color modeling order to help in the discovery process… that is focusing on the following as you walk through the assorted primary user scenarios:

  1. First trying to discover what time-sensitive aspects does the business care about most (the pinks)
  2. Then looking towards the roles that may be at play there (yellows).
  3. Are there any specific things (like contracts, purchase orders — greens)?
  4. And finally, any descriptive elements (blues) to go alongside the greens?

For the past 18 months, I am in major love with Ruby, Rails, and MongoDB — plus all of the surrounding tools and community (see my recent blog posts). Ruby the object-oriented language I wanted when I was doing C++, and MongoDB/MongoMapper is the OO-like DBMS that I always wanted. Putting it all together makes for real productive, high-quality, consistent development — I can quickly model out domain things and try them in a working application.

I’ve never done an adequate job of explaining how I like to approach doing just-enough design up front, but you can find a few snippets here:

Some tips that I find useful when doing initial up-front Domain Modeling (what you are about to do):

  • Spend time with subject matter experts and the business/product owners
  • Build out as you gather high-level features
  • Do breadth first, then depth
  • Only go into details when it will help reduce an unacceptable level of risk

That last bullet is key. I like to do just enough up-front work to please the stakeholders and myself that we can answer the question about: how much? and when? to the level of desired specificity. When you attempt a high-level estimate at a given feature, and it is too big for your comfort, then you can get more detail and break it down further so that it becomes acceptable.

If you do not do enough up front, and your estimate is off by an order of magnitude or three, you might upset the client!

On the flipside, if you do too much up front (detailed modeling), then you risk not getting frequent, tangible, working results into the hands of the client soon enough.

It’s a big balancing act.

Development with MongoMapper

A question popped up:

Mongo is schema-less, that means we can create new fields when needed, I read the mongo mapper document, it still needs to write model code like below, so we have to change the code below when we need new field, is this kind of limitation to use the schema-less database mongodb?

class User
  include MongoMapper::Document

  key :first_name, String
  key :last_name, String
  key :age, Integer

Strict answer: NO, you do not have to change the model code to add a new “column” to your “table.”

I like to think of MongoMapper as making my domain classes behave more like an object-oriented database than a data management layer.

During rapid development, having a database that just follows along with your model makes for speedy feature creation and prototyping. Though “migrations” being first-class citizens, of sort, in Rails is a great step forward for managing development changes with traditional schema databases, MongoDB doesn’t even require that level of concern.

That said, it also implies you, as the developer/designer/architect, are treated as an individual willing to take on the responsibility of wielding this amount of “power” (just like Ruby does).

Therefore, even though you do not technically have to add keys to your MongoMapper document class, if you are talking about core aspects of your domain, I would add the keys so as to make it clear what you are modeling.

Now, there may be certain cases where a class is just storing a bunch of random key-value pairs that are not key elements of your domain, with the sole purpose of merely showing them later. Maybe you are parsing data or taking a feed of lab results, for example, and just need to format the information without searching or sorting or much of anything. In this situation, you do not need to care about adding the (unknown) keys to the model class.

As the saying goes, “just because you *can* do something does not mean you *should* do something.”

You Can Start at Login!

On one of the lists I hang out at, Marton was wondering about how to start off a project that required authenticated users…

How would you decouple the sign-up feature from the login feature to keep the stories independent and testable from the UI only. The acceptance criteria should not fiddle with any implementation details such as concrete url-s or field types. I’d like to leave that entirely to the developers. Let’s say I have the following story coming to mind in a workshop:

As an Anonymous user I want to sign up to Example.com website to enjoy the benefits of a registered user.

Acceptance Criteria:
1. I navigate to the signup page
2. I enter my full name, desired username and my password
3. I have to verify my password to avoid any typos
4. I submit my information

And here comes the “tricky” bit:
5. I can log in with the credentials I provided.

Some folks suggested he start on real functionality first, others implied login was a lousy first story.

My take: It’s not a hard story to start at and have a meaningful test that can grow over time.

For example, to start, you can simply check that the response has “Login Succeeded” ( or “Login Failed” for testing that a bogus login attempt does indeed fail).

In Cucumber flavor:

Scenario: Registering as a new user
    Given I am a new user
    When I visit the site
    Then I can register

Scenario: Logging in as a registered user
    Given I am a registered user
    Then I can login
    And enjoy the beauty of the website

Or, even more simply:

Scenario: Successful Login
    When I login as admin
    Then I should be logged in

Scenario: Failed Login
    When I login as asdf56ghasdkfh
    Then I should be not logged in

And your steps would hide the logic for filling in the login form and checking for success:

Given /^I login as "([^"]*)"$/ do |login|
  @login_name = login
  visit login_path
  fill_in "login", :with => login
  fill_in "password", :with => "password"
  click_button "login_button"
end

Then /^I should be logged in$/ do
  response.should contain "Login Succeeded"
end

Then /^I should not be logged in$/ do
  response.should contain "Login Failed. Please try again."
end

Your login details can change over time, adding the password confirmation box, handle validation errors, etc.

Your next step might be to show Admin-user-only functionality as I have here (snagged from a current app):

Feature: Quickly exercise the primary UIs just to make sure nothing blows up

  Background: We need to pre-populate the database with the simulator results, and be logged in as admin
    Given I login as "admin"

  Scenario: Brief tour around the Admin UI
    Then I should be able to click on "Dashboard" and see "Admin Management"
    And I should be able to click on "Accounts" and see "Search"
    And I should be able to click on "Sign out" and see "Login to Your Account"

And so it goes, step-by-step.

Hope that helps!

As an update… one of the list contributors went so far as to indicate “Login has Zero business value, always.” No wiggle room there!

well, okay, if you are parsing the act of logging in to achieve a status of an authenticated user to provide a means of secure access as separate from the need to have secure access, well, ok.

yes, i didn’t separate the two. The point was merely to show the OP how you could easily write his desired login and registration story, and it is not that hard.

As an aside, another project I did with two friends required a “marketing” site where you could sign up and see info about the core application. The project also required the site where registered users would do the real work of the application.

Since I knew login would be easy to add, I suggested to my one friend how to do it, and proceeded ahead with the other functionality. This was based on knowing full well that I would be able to feather in the user authentication and access rights into the core app once they were completed in the marketing app.

So, I am not hard over one way or the other on this issue, and in the past 12 months have done it both ways on different projects. Hence my surprise at folks’ having such stark “black and white” edicts banning ever starting at Login as a story.

Now, were I on a project where there was some very risky bit that, should we not solve that problem adequately, nothing else matters, guess where we start? Not login. 🙂

Geesh.

Oh, George posted a reply of sorts here.

Mongo Remembers All Keys

On the MongoMapper group list, Nick was wondering about getting key names from the model. But he noticed it remembered keys that had once been used… He wanted to only be able to see the current state of his MongoMapper class, I suppose… No dice, Nick!

Remember, MongoMapper Don’t Care! MongoMapper also does not forget! You can always see what keys were ever used as demonstrated here:

MongoMapper.database.collection('users').drop
class User
  include MongoMapper::Document

  key :name, String, :required => true
end
User.destroy_all
text = []
text << "After model with key :name, String"
text << User.keys.keys.inspect

text <<  'User.create(:name => "Fred")'
User.create(:name => "Fred")
text <<  User.keys.keys.inspect

text <<  'User.create(:name => "Fred", :email => "me@me.com")'
User.create(:name => "Fred", :email => "me@me.com")
text <<  User.keys.keys.inspect

text <<  'User.destroy_all'
User.destroy_all
text <<  User.keys.keys.inspect

text.each {|t| puts t}

You can see how the model keys reflect what is in the model class and in the actual document store (that is, dynamically added via a create):

After model with key :name, String
["name", "_id"]
User.create(:name => "Fred")
["name", "_id"]
User.create(:name => "Fred", :email => "me@me.com")
["name", "_id", "email"]
User.destroy_all
["name", "_id", "email"]

Now let’s extend the model class to add a new city key:

class User
  include MongoMapper::Document
  key :name, String, :required => true
  key :city, String
end
text = []
text <<  'Extended the class, adding city'
text <<  User.keys.keys.inspect
text.each {|t| puts t}

As expected: there is the new key:

Extended the class, adding city
["city", "name", "_id", "email"]

Removing Keys

If you accidentally added keys, then you should remove them. For example, I accidentally had an uppercase key in the model for a while (oops). Here is how I eradicated it from the database store:

  def self.purge_msid_key
    uppercase_msid_acts = Account.where(:MSID.exists => true).count
    if uppercase_msid_acts > 0
      Account.unset({}, :MSID)
    end
  end

Related MongoMapper Issue: Track Loaded Keys at the Instance Level

You Don’t Always Have to Follow “The” Rules

A user was asking the following on the Agile Modeling list:

What experience does anyone have about standards for stories written for
non-UI components? I’m working with a proxy PO who feels the standard story
format (As a <user> I want to <activity> so that <purpose>) simply won’t
work for something that doesn’t have a user interface. Imagine, for this
example, a project that has the sole purpose of encrypting data without any
user interaction.

For my needs, I often apply the principles behind the concepts, if not always the exact template of a suggested practice. Take for example, the use of my favorite tool, Cucumber, to write Acceptance Tests. Typically, cukes are written from the user point of view in classic “Given – When – Then.” But sometimes I like to use the cucumber style for testing APIs that I am building.

Here is one example at the Cucumber level (with the companion RSpec shown below):

Feature: Version 2.0: As we parse PDFs, we need to be able to collect a list of fonts
  as a way to help discern the structure of the parsed document based on
  heading levels, density of upper case text, and what not.

Scenario: Parsing a simple document
  Given a sample set of text
  |reference|points|value|
  |R9| 10| Patient: FRANKLIN, BENJAMIN|
  |R9| 10| CHIEF COMPLAINT:|
  When i parse the text
  And provide a set of base fonts
  |ref |basefont|
  | R9 | Helvetica-Bold|
  |R10 | Helvetica     |
  Then I should have the following font stats
  |reference|points|upper_cnt|lower_cnt|percent|
  |R9       | 10   | 4       | 1       | 83    |
  And the following font names
  |reference |points|basefont|
  |   R9     |  10  |Helvetica-Bold|
  |  R10     |  10  |Helvetica     |

Scenario Outline: Parsing a simple document
  When collecting a set of text , ,
  Then I should have  and  word counts and  Uppercase stats

  # Note: the counts are cumulative
  Examples:
    |reference|points|value|upper_cnt|lower_cnt|percent|
    | R9| 10| "Patient: FRANKLIN, BENJAMIN" |  2 |  1 | 66 |
    | R9| 10| "CHIEF COMPLAINT:"            |  4 |  1 | 83 |
    | R9| 10| "PRESCRIPTIONS"               |  5 |  1 | 89 |
    |R10|  9| "Motrin 600mg, Thirty (30), Take one q.i.d. as needed for pain, Note: Take with food, Refills: None."| 0 | 13 | 0 |
    |R10|  9| "(Discount Medication) < Michael L. Panera, PA-C 7/13/2010 17:40>"| 0 | 17 | 0 |

And here’s another one:

Feature: Extract meaningful data from Discharge Message

  Scenario: Extract headings
    Given a discharge message
    When the message is parsed
    Then I should see meaningful information, structured as headings and paragraphs
    And I can get formatted values for HTML display

  Scenario: Extract headings from second message
    Given a second discharge message
    When the message is parsed
    Then I can get formatted values for HTML display

But wait! There is more!

At the “Unit Test” level, RSpec’s can be made rather “english friendly” yet still be all about the underlying API as this diagram and snippet show:

RSpec for an API

The Font Collector RSpec tests

describe PdfParser do
  describe PdfParser::FontCollector do

    before(:all) do
      PdfParser::FontCollector.clear_all()
      ...
    end

    context "initialize" do
      it "should reject missing font reference" do
        ...
      end
      it "should reject missing points" do
        ...
      end
      it "should reject missing value" do
        ...
      end
      it "should accept valid inputs" do
        ...
      end

      it "should start off with simple stats" do
        ...
      end

      it "should recognize reference+size is unique" do
        ...
      end
    end

    context "clear" do
      it "should clear the font list" do
        ...
      end
    end

 

Pair Programming Comments

Yves Hanoulle had some questions from class participants on his post about Pair Programming. I am not a very experienced pair programmer, but that didn’t stop me from providing some answers 🙂

* Can you PP over skype?

Yes — or other similar screensharing technologies (iChat) that allow you to switch control. @jbrains and I did pairing for a code retreat a couple of months ago. You can see the code and a video link here on github.

* Do we need somebody to ‘supervise’ the way you do PP ? (Esp in the beginning?)

Might not be a bad way to more quickly learn from someone else’s tips and techniques. But even better, just switch up the pairing so that you gain insights/ideas from other people with more experience.

* What if there’s no option possibility to use some OS/Computer

With no computer to program on, you would have to stretch the limits of the definition of pair programming I suppose. Pair Yapping About Programming — P-YAP?

* What to do if there is a conflict between the two, a discussion??

Try and sketch out the competing ideas in code. Unless the argument is about which beer is best… then you need to take it to the bar and do a double-blind taste test.

* It can’t work with any type of character, how do you manage?

Pairing should be optional.

* What if one uses AZERTY and another one QWERTY keyboard?

You could solve that with technology.

* Doesn’t it make it harder to plan a project or resources people (Yves re-framed resources to people)

I would suspect the team that pairs is not that much different than a team that doesn’t pair. Both teams are probably lousy at estimating <g>. Instead of stressing at how PP affects your team, just make an initial guess at your estimates and alter the guess after each iteration.

* Can someone do PP with 1 person and PP for something else with another person?

I don’t understand the question. If you mean simultaneously, no. If you mean one time someone does Pair Programming with person X, and later does Pair Painting with Person Y — sure, this is possible. But what does it have to do with anything?

* Can you get into “the zone” when you’re PP-ing?

Probably. You’ll just have to try it and see.

* Does Promiscuous Pairing kill the flow? (30′ interrupts)

Never tried it. Let the team try it and see what happens.

* Why not use PP all of the time?

Let the team try it and see what happens.

* PP = More talking = more annoying for other nearby teams?

It is more annoying for people that are bothered by such environments. I suppose some people prefer quiet.

* Do you plan who is going to do what or how do you choose whose turn it is?

Let the team decide.

* Can you do PP with > 2 people?

You can do whatever you like. Just observe if it is effective or not. I suspect you might find diminishing returns.

* How do you handle the “Don’t care”?

What does this have to do with PP? If you have done everything humanly possible to help someone become a productive member of the team and they are intent on being a-holes; and you have warned them of the consequences of being an a-hole to the team; then fire them so that the team morale is not broken by “one bad apple.”

Cucumber Parser Smarter Than Me

So that I don’t lose another 15 minutes… I had a step like this:

Given a valid outpatient A01 Admit message (without extra ZP1 segment) with Patient Num "12345678"

And in the steps.rb file:

Given /^a valid outpatient A01 Admit message (without extra ZP1 segment) with Patient Num "([^"]*)"$/ do |pn|

Which happily kept not working:

You can implement step definitions for undefined steps with these snippets:
And /^a valid outpatient A(d+) Admit message (without extra ZP(d+) segment) with Patient Num "([^"]*)"$/ do |arg1, arg2, arg3|
  pending # express the regexp above with the code you wish you had
end

UGH!

After getting rid of A01 and ZP1, I still had this “error,” but it led me to realize it was ALL in the parentheses in the steps.rb file! Why? Because parentheses are valid regex elements. Duh. Once I escaped those, all worked like a champ:

Given /^a valid outpatient A01 Admit message (without extra ZP1 segment) with Patient Num "([^"]*)"$/ do |pn|

Mystery solved.

MongoDB Honey Badger

In case you don’t know about the Honey Badger—you have to watch this video. Then you will see why MongoDB is a close cousin to this feared and fearless animal!

Developing a new project where your domain classes/tables are changing rapidly?

MongoDB don’t care!

Tired of running rake db:migrate?

MongoDB don’t care!

Need to add a new “column” to your “table?”

MongoDB don’t care!

Want to query your “table” on “columns” that don’t exist?

MongoDB don’t care!

Need to add a new index on the fly?

MongoDB don’t care!

Welcome the Nastyass MongoDB into your development lair, you won’t give a shit about your database growing and changing!

MongoDB don’t care!

Find out more about Honey Badgers here — though Randall already taught us most of the salient points!

 

The Website Development Anti-Pattern

I don’t want to come down too hard on the author, he looks like a real nice, friendly guy. Writing a post like this took time, effort, thought, and care — which I applaud.

But when I read this post on Website Development — A Practical Methodology, I had flashbacks to Waterfall-esque DoD projects. Seriously? A phased approach with no partial deliveries, no iterations, no “sneaking up on the solution?”

Is this a post from, like, 1986? A phased approach?

  • “Once everything has been appropriately documented, it is time for the Implementation Phase.”
  • “Once implementation is complete, it is time to test.”
  • “When the testing is complete… you are ready to deploy.”

I humbly submit that you might want to intersperse some of those activities into a more iterative approach to reduce the time and cost of getting things wrong and discovering it late in the phases.

I just checked the date of the post again.

It is 2011.

Someone pinch me.