Software process and the ilk

Tuesday, August 15, 2006

Unpacking Packages

Many programming languages define ways of organizing code components into larger structures. In Java, these are packages. In C#, they are namespaces. If our application is large enough to need multiple packages, how we define those packages needs serious consideration. What are the goals of multiple packages in an application setting? What should we look for?

Goal: Conceptual Integrity

First and foremost, we want our packages to mean something, to make a Statement. The Statement should be simple and bold, and everything within the package should be geared toward that goal. Statements like "THIS is how the user interface works!" or "Interact with networks here!" are good. Statements like "talk to Databases and interact with users" are probably too complex, but we might be able to rephrase with "Let users manage databases" and be okay. Conceptual Integrity allows people looking for solutions to know if this package is right for them, and it allows everyone working on our application to know if they're developing for this package. It allows us to partition requirements into logical pieces, such that one requirement change will impact the smallest number of packages, and thus hopefully the smallest amount of code. It's probably the single most important reason to have multiple packages.


Goal: Reuse

Just like we want methods reused and classes reused, we want our packages to be reused when appropriate. We want to take that package we wrote for feature 1 and use it for feature 2. Probably this means some refactoring – the first pass may have been pretty feature specific. It's worth the effort, though:

  • Debugging one shared package will be much more fruitful than debugging two.
  • Experience and statistics tell us that repeated code will result in repeated bugs.
  • Testing one package is faster than testing two.
  • Removing a defect in one package removes it from all components that use that package.

  • We would love for that package to be useful in a completely different application. If we can get someone else using it, any defect they find is one we don't have to look for. Fix it, and make the package better for everyone. Don't waste time trying to write the ultimate reusable package, though. We're supposed to be writing an application, not a library.


    Good Practice: Cautious Outer-App Package Dependencies

    Maintenance is not just about requirements: we also have to worry about packages we depend on. Every time a package dependency changes, we need to at least run through an entire testing suite. At worst, we need to do a very big rewrite. This means we want to rely on packages that aren't going to change much. Note this doesn't necessarily apply to packages within our developing application; this means all those 3rd party packages we're trying to exploit. Make sure they're solid.


    Good Practice: Avoid Dependency Cycles

    Dependency cycle: package A depends on package B which depends on package C, which depends on package A. Avoid them. For one thing, as my college Brian points out, if we have dependency cycles, we're probably violating conceptual integrity in some of those packages, and so we're losing the biggest use for our packages.

    Another reason cycles are bad: possible infinite testing. If we have control over all the packages involved, we can cheat here. Sadly, we don't always have that luxury. Here's the problem: Package A is updated, and package C needs to change in response. Now package B has to be checked and also gets updated. Suddenly we're back to package A – dependency cycle. Without exclusive control over everything involved, this could go on ad nauseum. The whole set, packages A, B, and C, might as well be collapsed into one big package while such a lock exists, and that huge package will not have a simple Statement. We've just broken Conceptual Integrity. Cry.


    Good Practice: Package Ownership

    For each package, define one person to be the "Owner". The primary responsibility is to ensure the package maintains its conceptual integrity: that it remains true to its cause. This person waves the red flag if something goes wrong with the package; this person watches for dependency cycles; this person probably writes lots of tests for the package. This person is the package's mother.


    Question: Where's the glue?

    "Reuse is great and all, but we can't take Bob's Database Package and use it out of the box – we have to write special code to make it do what we want to do." It's this glue code that makes an application something useful to Housewife Sally, who doesn't know or care about code.

    Whoa, slow down big fella. Our packages ARE the glue code. We're not writing libraries, remember? We're writing an app. It's okay to have a package where various pieces come together; somewhere in all this, after all, we need to RUN the program. That can be a package Statement: "This package makes the program go."


    Question: Dependency paths and fixing bugs

    So, we've got this great package, but we found a bug. And we fix the bug. Good for us! We're even pretty sure we fixed the bug without any repercussions; our whole super testing suite is solid and passes everything just fine. This all means that packages that depend on us don't have to worry about anything, right?

    Wrong. For one thing, we changed code. "That means we may have injected a defect", says someone with super clean hands. Small chance, maybe, but dependant packages can't take the risk – they're at least going to run through their test suite.

    For another thing, we may have changed something circumstantial that outside packages depend on. Maybe we used to return a list sorted by last name, and now we return it sorted by first. Doesn't matter to us, all we promised was a list, but somewhere someone realized they were all sorted one way, and used that fact. Now that assumption (bad on their part) is broken, and they have to deal with it. Not our fault, per se, something they have to take into account.


    Summary

    Developing to packages within our application is harder than developing just to our application. Packages are intended to be reusable, which means more flexible. More flexibility means more paths of use, and in turn means more possibility of defects. This means more initial design, more development, and more testing. Why program to packages, then? All the standard, good reasons: Abstraction, Encapsulation, Information hiding, Maintainability, Understanding. Working hard to ensure we have a well architected system will save us down the road. But we need keep a good head on our shoulders - it's easy to try to make things too flexible, too general when our app doesn't need it. And the app is the reason we're here at all.

    Tuesday, August 01, 2006

    Password Protected

    Today, passwords are like wild flowers. Take your pick, you can have as many as you want. Solely for work, I have four passwords - email, timesheet, and 2 different project repositories. Wait, make that five, access to internal machines. Purists will tell me that's ridiculous; all those (at least the first four) should be the same account, and so the same password. Perhaps, but my IT staff aren't purists; politics (ie real life) gets in the way. Besides, I don't want to complain about such things, I just want to know what my password is.

    When I get home, I another four or five passwords I use regularly: (personal) email, bank accounts, the all important nethack, Ebay, B&N, ... You get the idea. I have so many passwords, I forget my last name. Add on these important Good Password Tips:
    • No two passwords should be the same
    • No password should be written down
    • Should not contain any word in the dictionary
    • Passwords should be impossible to remember
    Now add some of my favorite rules REQUIRED by some systems:
    • System A:
      • Total length must be at least 6 characters
      • Case sensitive
      • Must contain a number
      • Password must change every 90 days
    • System B:
      • Must use three or more character classes (upper case, lower case, symbol, number)
      • Total length must be between 7 and 23 characters
      • Cannot be any of the most recent 3 passwords
    If you're like me, the set of rules is completely unrealistic. I have to have 10-20 passwords that are not written down, impossible to memorize, longer than 6 characters, and tied to a particular account.

    Online tools that create pseudo random passphrases are okay, but every 90 days I have to remember another arbitrary string. That's painful. Here's the system I use to deal with all this.

    Pick a song, poem, speech, or passage to memorize. It should be relatively arbitrary, but relevant to you. In other words, it should be something you want to memorize. The Gettysburg Address, a Psalm, a Shakespeare sonnet, Jabberwalky, anything works as long as it has multiple sentences and is at least a good paragraph length, say 50 words. We'll use the following example:

    Once upon a midnight dreary, while I pondered, weak and weary, Over many a quaint and curious volume of forgotten lore, While I nodded, nearly napping, suddenly there came a tapping, As of someone gently rapping, rapping at my chamber door. " 'Tis some visitor," I muttered, "tapping at my chamber door; Only this, and nothing more."
    Now, whenever you need a password, pick a number.
    If today is the eighth, choose 8. Then we'll start with the eighth word: pondered. Now how many letters need to be in the password? Say 10. Then we look at the phrase starting at pondered and counting for 10 words (treat punctuation like words):

    I pondered, weak and weary, Over many a

    Take the first letter of each word, including punctuation again:

    Ip,waw,Oma

    Hmm. That looks like a pretty good password. Three character classes, fairly random. Also, it's easy to memorize the pass-phrase: you already know it. Here's another key: as long as no one knows your pass-poem (Poe's The Raven in this case), you can write down key information. Here, we start at the eighth word and use ten words. Write down 8,10. I usually write down lots more, because there's lots you have to remember if you don't use the password often:

    ebay, icarus, 8, 10

    The advantage of this system is that lots is kept in your head, but the tricky stuff is written down. You memorize one poem and write down keys into that poem. And, unless you're like me and tell everyone your system, people don't know what 8,10 means at all. The pass-phrase is cryptic and the algorithm is cryptic. It's not fool proof, but it's a lot easier than other methods I've tried for the long term. (Don't write down your key next to your pass-poem!)


    Special cases: No Punctuation
    Some systems don't allow punctuation: then when counting for the phrase, skip punctuation. Write down a minus to indicate you didn't use punctuation. From before, using 8 and 10 again, we get

    pondered weak and weary Over many a quaint and curious

    which becomes:

    pwawOmaqac

    and you write down:

    ebay, icarus, 8,10-

    Note the minus at the end indicates you ignored punctuation.