Uber Fail

I wouldn’t normally pollute the internet with stuff like this, but I always tend towards the cynical when much feted, “tech-savvy”, market defining, paradigm shifting companies show us that their mastery of technology and process is really no better than anyone else’s.

Firstly, I was on the Uber website and accidentally started the process of registering as a driver – which was not what I wanted to do.  My bad, I admit that; anyway usability of the website’s not the main focus here.

I soon start getting SMS message’s as part of the “new driver” process.  Ooops, I had better reply STOP to unsubscribe…

Oh dear, did anyone actually test that unsubscription works, or do you:

  1. Have shares in the Telco industry
  2. Forgot to implement it
  3. Deliberately not implement it

wp_ss_20170501_0001wp_ss_20170501_0002wp_ss_20170501_0003wp_ss_20170501_0004wp_ss_20170501_0005wp_ss_20170501_0006wp_ss_20170501_0007wp_ss_20170501_0008

But we’re not quite done yet.

I’m not just getting enduro-spammed via SMS, this is a multi-channel affair:

uberemail1

Although the email campaign has it’s own issues – nothing major, just the occasional missing subject line and total absence of any content.

Oh, but at least the template is nice.

uberemail2

@Uber #STOP

 

WSAF Survey 2015 – Results

A while back we put a survey questionnaire to the architect community via Meetup.com and LinkedIn, which included questions such as:

  1. How long have you been in IT?
  2. How long have you been an architect?
  3. What Title best describes you as an architect?
  4. What did you do before you became an architect?
  5. Career progression: what role do you aspire to move into next?
  6. What is your biggest challenge as an architect?
  7. Do you feel you are effective as an architect?
    • Why? Please tell us what you feel makes you effective / ineffective as an architect
  8. What advice would you give to new / aspiring architects?

Despite having 680 WSAF members on LinkedIn, and 142 on Meetup.com we only managed 10 responses.

In some ways it was far less than we were hoping for – given our numbers on paper.  I do acknowledge that as organizers of the group, the WSAF isn’t perhaps as active as we’d like to be, however, it might also be a reflection of  the local kiwi architect culture, and symptomatic of the channels we currently use to reach you all.  Community engagement is an area we are conscious of and something we’d like to increase in future.

The Results

Whilst the low response rate may render the quantitative results less than statistically sound they did provide some interesting insights.  Some of the questions were more qualitative provided some quite thought-provoking comments.

You can download the raw results here: https://onedrive.live.com/redir?resid=2942088AAC497628!4940&authkey=!AJstOf7P6LaCOZU&ithint=file%2cxlsx

[The results (xlsx) and images posted here are hosted on Microsoft OneDrive, let me know if you are having trouble accessing them.]

Who Responded?

In terms of roles most of you were, unsurprisingly, Solution Architects or Enterprise Solution Architects:

Title

How Long?

  • How long have you been in IT?
  • How long have you been an architect?

As you can see, most of the respondents have been in IT for 10 years or more, in fact mostly for 16 or more; but a relatively even spread of years experience as an “architect”:

How Long

Career Progression

We asked what people had done before they became an architect and what they think they’d like to do next.  As you can see, software development is a common starting point (I notice we didn’t get any Infrastructure Architects responding) with Enterprise Architecture looking like the most popular next destination:

Career Path 2

Effectiveness

I’m extremely pleased no-one felt categorically ineffective, but then there wasn’t exactly an over abundance of confidence either: half of our respondents answered “yes” whilst the others said (typically for architects) “It depends”:

Effective

Selected Comments

In closing, here’s a selection of comments we received to the more open-ended questions:

What is your biggest challenge as an architect?

“Inter-Personal communication, especially when doing Enterprise level work dealing with application level architects.  Some cannot see the forest from the trees and want to re-litigate the “what” (strategy aspects) instead of focusing on the “how” (how to make it work to achieve the what outcomes).”

“Understanding the role within the political landscape, and being able to effectively convey this role to business and it people who don’t understand/value the role of an Architect.”

What do you feel makes you effective / ineffective as an architect?

“I think of myself effective when I align architecture with the business strategy and maturity. Not the best architecture, but the best fit architecture for an organisation at their particular maturity, budget and strategy level make me an effective architect.”

“Effective with a balance of inter-personal skills and technical abilities.”

What advice would you give to new / aspiring architects?

“Focus on the outcomes and what constitute success for the business, not so much the process of architecture (standards, practices, the next best thing), but more the product of architecture (alignment, value, outcomes).”

“Use Rozanski and Woods.”

How Not to Screw Up an RFP Response

Originaly posted by AdrianK, 26-Jan-2010 at:

Vendors typically have to expend a huge amount of effort when responding to an RFP.  This article looks at how they can help themselves (and thus the client), so that the effort isn’t wasted.  The short answer is that whist RFP respondents typically focus on the solution they are offering, the real key is to take the human factors of the reviewers into consideration.

In my role as a Solution Architect (or perhaps just by being one of few resident development skilled geeks) I contribute to the RFP process – on the client side.  I’ve also done a wee bit on the vendor side too.

Having done a string of RFP reviews in recent times I feel compelled to provide some feedback to those of you out there who submit RFP responses; and whilst most of you are doing well there are others who (with all due respect) desperately need some help.

[A bit of context – this feedback is based on experiences within the New Zealand public sector.  I can’t vouch for other countries but I’m sure a lot of these points are transferable].

Before I lead us through the vast litany of unfortunately very common mistakes, let me give you some insights into the life of a RFP reviewer so that you can understand the context in things happen.

RFP’s are generally structured into sections with specific statements and questions within each; for the review, reviewers will be given a pre-defined score sheet from the contracts team (who usually oversee issuing of the RFP), and it’s no mistake that the score sheet utterly reflects the RFP.

Some score sheets expect the reviewer to individually score each answer and question pair; others expect a single score per section of questions. 

When I’m reviewing responses that require score by section, I generally work through each section in turn for all responses, in other words I work by section not by response.  For example, for a recent RFP review I was reviewing a stack of hardcopy responses:

  1. I usually start with a very brief flick-through of all the responses to get a feel for what’s coming.  The score sheets are usually in Excel all setup with the respondents entered and formulas ready to aggregate results on a separate worksheet (which I avoid looking at until the end of the review).  I stack the responses in the same order they are in score sheet.
  2. I’ll review the RFP itself again, as well as the question and answer sets that have been created – and I’ll have full print-outs of each at hand.
  3. I’ll then start the review proper, starting with the first appropriate section and the first response, then moving on to the next response.
  4. Once I’ve scored all responses for the current section I’ll move on to the next.
  5. If a section to be reviewed is large or covers multiple topics (they aren’t always as cleanly segregated as you might want) I’ll setup a more granular sub-score sheet of my own somewhere; in this case I might start reviewing responses per individual question, but not always.

Additional notes for each score are also entered; these are pretty essential for the final group review.  As you might know the RFP’s will be reviewed by a group of people who will then come together to thrash out a result (or a short list).  In a recent case my review took a full week (including normal day to day interruptions) thus the notes are essential.

Once the reviewers have completed their individual reviews (and scoring) they all get together for a formal review and scoring session where the final grading is done – this is the bit that counts.

The crucial point is that reviewing RFP’s is long and tiring work, particularly if there are a lot of responses, and it’s harder with responses that are of a poor quality.  Thus one of the keys to a good result is to take the human factors of the reviewers into consideration – make your response a pleasure for them to score.  So, how do you actually do that…

Structure

If you want best “bang for buck” this is the mistake you can’t afford to make: as mentioned above RFP’s and there score sheets stick to the same structure – deviating from that structure in your response is asking for a serious amount of pain and may well land you in the bottom %60 of scoring.

When you have to review and score a dozen odd responses you don’t have time to hold peoples hands – if the your response clearly follows the RFP structure the reviewers won’t have to think [1] in order to find the information to review, and they’ll thank you for it.

Use section names and paragraph / question numbers from the RFP to label the content in your response, and include this in the table of content if appropriate: make sure it’s really easy to scan, use decent indenting, bolding and other presentation techniques to make it so – but don’t go overboard. 

With most RFP responses, at least some of the respondents will do just that; this consistency makes it easier for reviewers to work with those responses and the more that do this the more they will all benefit from the consistency; correspondingly, failing to do so will put your response comparatively on the back-foot.  This is particularly true the more responses there are.

Next on the priority list is a decent Table of Contents (ToC), and please, please, please don’t forget page numbers.

What you want is a nice, clear, easy to read ToC which matches the RFP structure, with page numbers so I can jump straight there.  “Hand-Over”?  Oh look its on page 28.  “Security Testing”?  Page 13, bingo.

RFP’s that do none of this are so awful to review it’s not funny, and it takes little imagination to guess how that impacts on scoring, after all you can’t score a response you can’t find.

I’ve seen everything in between: responses with no ToC, ToC but no page numbers (bizarre) and page numbers but not ToC (near pointless).  The sad truth is that whilst the reviewer should be scoring you on you content, you’ll get scored on your delivery instead – if it’s poor. 

This brings up an interesting point, in that (for the reviewer) there’s often a fine line between scoring the response and scoring the way it’s delivered, and the division between the two can get quite murky at times.

Finally, RFP reviews always include a section for presentation and delivery; these should be easy points to win if you follow some of the advice above.

Content Quality

By this I don’t mean that you offer a database that is redder than everyone else (a red database is fastest, yes?); what I mean is that your response must answer the questions that have actually been asked.  You might think this was obvious, however, I regret to inform you that the obvious is obviously not that obvious.

Failing to actually answer the question is at least as dangerous as ignoring the RFP’s structure.  First tip: actually read the question.  Read it again and make sure you understand it.  Count to ten before you start writing.  Discuss it with a peer.

It’s tempting to respond to the “training” section of questions with your standard training blurb – don’t rely on this.  Make sure you understand the specifics of what is being asked and directly answer it – make it as easy as possible for those poor tired reviewers to give you full marks.

Responses that (reading between the lines) suggest the respondent is capable – but which don’t directly answer the exact stated question put the reviewers in a tricky position. 

If in doubt answer the question directly (‘what they asked – not what they meant”, as strange as it might sometimes appear) and then additionally provide a ‘second’ answer that answers “what they meant not what they asked”.

In short: make sure you directly and specifically answer all the mandatory questions in the RFP.  Reviewers generally mark a score as set-out in a predetermined score card (most likely defined by the internal contracts team); one of these options will cover responses that fail to answer questions specifically.  Often questions can be lumped together into section and a score is given for the section as a whole – if you don’t answer all the mandatory questions you risk being thrown into the ‘failed to provide a response’ category even if you did answer some of the questions.

Consider very carefully when asked to describe your approach to completing a specific deliverable; is the RFP trying to elicit the steps you go through or your thinking behind those steps?  It is – trust me.  Knowing what your process is can be illuminating (but not always in the right way) where-as getting an understanding of why you do it that way is often more helpful – it shows that you can justify your approach or might suggest that (due to your understanding) you can compensate when variations occur.

“All software we produce under goes our comprehensive range of time-proven of software testing techniques” is not going to score you anything.

“All software component testing is automated using N-Unit with code coverage of at least %80 by the end of every sprint.”  Is much better – I know the tools you use, it looks like you know what you’re talking about (code coverage) and your testing is integrated with your development methodology (don’t tell me you’re “agile” elsewhere in the response and then fail to mention relevant agile practices where appropriate).

Content Quantity

Reviewers will be looking to get the review done as fast as possible – be as succinct as possible – both in volume of text and presentation.  The average reviewer may not be too interested in a whole page executive summary

(although this kind of thing may be useful to others?).  Also, the bigger the document is the harder it will be for reviewers to find information if it’s not blatantly obvious from the table of contents.

The balance between too much info and too little can be a very delicate one, and it’s easy to get wrong.  One approach that might work for you is to provide some level of detail (to try and expose your depth of knowledge) but not for the whole breadth of the issue

Pick you targets; make sure you understand the RFP and your relative strengths and weaknesses, what responses are you giving elsewhere?  Some questions will lend themselves to a longer answer better than others, and for others a shorter answer.

If the RFP simply states that you need to confirm acceptance or acknowledge something then do so (assuming you accept, of course); something like “We confirm acceptance of this requirement” should do the trick.  Evaluate the question – don’t feel you need to give additional info if it’s not necessary. 

If you add additional information please make sure you still formally state acceptance as a clear acceptance is the fastest way to full marks. 

Starting with the acceptance and then providing additional info is probably best.  One advantage of sticking to the acceptance statement only is that it means you can add more content elsewhere; save yourself for where it’s worth going the extra distance, so that the overall response isn’t bloated.

Name drop – Mentioning the names of specific processes and technologies can be a very useful way of conveying a sense of depth without going into detail, for example: when questioned about security testing name-dropping specific threats demonstrates a knowledge of the domain – “… protection against SQL Injection, XSS, and Drive-by attacks…” makes it sound like you know what some of the potential and specific threats are, where-as simply saying you’ll defend against malware is very vague.  Of course anyone can name-drop things they don’t actually know anything about, but the rest of their answer (and the way it is written) should give an indication as to the overall authenticity of their knowledge (as will the response overall).

Name-dropping is also useful in that anyone scanning a page of text might recognise words which catch their interest – and so lead them to actually read your response more closely.  Conversely – a lack of ‘buzz-words’ might imply that you’re merely waffling.

Conversely, be careful not to rely on name-dropping alone; there are definitely circumstances where it’s worth putting a small degree of appropriate fluff around things; and also along these lines it’s a good idea to provide the full name rather than the acronym only.  For example, when listing relative experience:

  • Wrong:  SOA
  • Good:   Service Orientated Architecture (SOA), 5 years experience.

Don’t wax lyrical about the subject if it’s not directly answering the question, for example: don’t discuss the advantages of standards compliance if the actual question is to simply state how you actually ensure the standards are met.

Presentation

Have you ever been guilty of judging a book by its cover?  Presentation counts – and done right it’s easy an ‘easy’ way to earn points.

There are a number of points to this: the obvious visual and aesthetic aspects and (the less flashy but just as important) usability aspects like layout and wording.

An optional but useful technique is to prefix your individual responses with the actual question from the RFP, this leaves the reviewer in no doubt they have found the right content.  A clearly headed and structure response should negate the need for this – so it does depend on how you want to present your response.  It can also help whoever is writing the response to stay focused on target. 

If you have supplementary information in other parts of the document mention it clearly at the end of the ‘formal’ part of the response to a specific question.  Supplementary info is good but may not always be read in full by all reviewers:

  1. Reviewers will focus on the formal responses first and they may not review supplementary content particularly if they are under time pressures, tired or feel overwhelmed.
  2. If the reviewer thinks they have formed a sufficient opinion based on the ‘formal’ answer to a question they are unlikely go looking for additional info.

Including additional sections of information is fine – just make sure it doesn’t get in the way; reviewers hate having to wade through a big thick document just to find the information they need.

Never attach core information separately to the response (“sample widgets attached as jpegs”), if it’s worth including in the response please embed it in the actual response, and ensure it looks crisp when printed / photocopied in black and white (because not everyone will print in colour).

One approach is to include a “lesser” (but usable/readable) example in the RFP response document and a big flash high-res copy as an attachment – if the lesser example wets the reviewers appetite they’ll be more likely to go to the trouble to look at the separate attachments.

Think about who will be reviewing the responses: it will be a range of people with various skills and knowledge; what they will all have in common is (probably) a lack of time, tiredness and a lot of responses to go through – make it easy for them.

A lot of companies have pre-defined templates for making pitches, and some of these appear to be used for RFP responses; by all means use these as checklists or something to spark though on the response – but don’t use the template for the response: it probably won’t relate to the structure of the RFP, and will attract the pitfalls mentioned above.  In addition, a response whose structure bears little resemblance to the RFP makes it look like you haven’t even read the RFP – a sure-fire way to get the lowest score (or risk getting thrown out altogether).

Website focused RFPs’ will typically have requirements around the aesthetic needs of the website; don’t provide text only answers – visuals are a must.  Be pedantic over how these are displayed – they must be high quality (Nothing beats a quality full colour reproduction of a nice visual).  Think about how the RFP is going to be actually delivered (usually a combination of both hard and soft copies).

When binding the response make sure it’s easy to turn the pages and that all the content on the page is clearly visible.  Responses that sit fully open on any given page are a blessing – ones that refuse to sit still without folding over are painful.  Ring binding is good, avoid staples and paper clips.

At the end of the day – if the RFP calls for a solution with any sort of aesthetics you don’t want a poorly presented response; if your response looks mediocre it won’t give the impression you can deliver a ‘killer’ design.

Thinking Ahead

RFP responses are usually reviewed by a group of people – usually selected to provide a range of stakeholders and expertise.  You’ll have business focused reviewers (perhaps end users of the system) as well as reviewers who are there mainly for the technical aspects.  These different audiences may or may not have the same degree of sway within specific areas of the review. 

One thing to consider (for example) is the kind of language used to answer a certain question, for example: answers that require a technical response will probably require a different language style than answers that deal with more empirical subjects like visual design and user engagement.  Think about the kinds of people who will be reviewing your response – and not just the response as a whole but also those that might focus on a specific area (technology, business, project management, and so on). 

Get your geeks to write the technical content, chances are the reviewers will rely on the geek reviewer to help guide them during the final review session where the final scores are thrashed out.  The same applies to other sections of the response – get the most relevant person (like the appropriate Subject Matter Expert (SME)) to write the content for a given area; get others to review and critque their work but becareful not to stamp all over their style and approach too much if it’s likely to appeal to the corresponding SME on the clients side.

Staff / Resourcing / People

One of the sections you’ll find in a typical RFP is one that requires you to provide information on the staff who’ll be working on the project, and you’ll usually be asked to explicitly state staff members by name against specific roles.  This will be mandatory – so make sure you do it.

Make sure you answer the question – kind of obvious; don’t just rattle off the standard blurb (unless it’s fit for purpose) – it’s easy to slip into making the mistake of covering someone’s past history even if it’s not directly applicable.  Make sure you directly and clearly answer the specifics of the question before adding details about what you do in your spare time.

Typically you’ll be asked to provide relevant details as to the experience of these people, perhaps in the form of a one page CV, there are many pitfalls here to be wary of – including all the baggage that usually goes with good CV writing, but there are several simple things you must do to avoid a bad review:

  1. At the very least: state the number of years experience in the relative field.  Stating the number of years the person has worked for your company is pretty much irrelevant – say that if you want to, but only in addition to their total relevant experience.
  2. Stating relevant skills, projects, technologies and so on is good but not enough on its own (see the ‘name dropping’ section, above).  Please don’t provide three pages of waffle and not state the total number of years of relevant experience.
  3. Provide all Staff CV’s / Bio’s in the same format.
  4. Pictures aren’t mandatory but are generally a good idea – people like seeing people.  Make sure the photo quality and reproduction are excellent otherwise the value of having the photos will be diminished or may backfire completely.

RFP requests are typically after a well rounded solution (for example, if its a website there will probably be business, aesthetic, architectural, development and testing aspects that need addressing), bear this in mind when providing staff bio’s.  I’ve reviewed RFP’s that needed a breadth of skill, and seen responses that listed a bunch of developers or designers and little else. 

Don’t be afraid of out-sourcing.  As a general rule I’ll give more points to a response that out-sources security testing to a specialist [2] firm rather than one that does it in-house, although this can depend on the size and skill of the vendor behind the response.  That’s my personal position, and not everyone has the same views as me.

I guess there’s the potential for that to backfire if the owner of the RFP has some pre-conceived idea that they want a single vendor to deal with.  If you’re a small firm then I’d say you’re better off taking the out-scouring route, and you can always have them working for you as a sub-contractor – so there’s still only one point of contact (and invoice) for the project owner to worry about.  Just make sure you’re clear in your response.

In Conclusion

Writing a good RFP response is learnt skill and it’s evident when the response is coming in from someone who has done it before, but you have to start somewhere.  It’ll be your team that does the actual work if you win – so you’ll stand the best chance of winning if the team contributes to the response.  Allow yourself plenty of time, check the basics – and go get ‘em!

References

http://en.wikipedia.org/wiki/Don’t_Make_Me_Think1. http://www.morphological.geek.nz/blogs/viewpost/Peruse+Muse+Infuse/The+Laws+of+Specialisation.aspx2.

Some rights reserved.  http://creativecommons.org/licenses/by-nc-sa/3.0

Converting Waterfall Requirements into Underground Agile Features

(Originaly posted by AdrianK, 20-Sep-2010 at: http://www.morphological.geek.nz/blogs/viewpost/Peruse Muse Infuse/Converting Waterfall Requirements into Underground Agile Features.aspx)

Converting Waterfall Requirements into Underground Agile Features

Well here’s an interesting thing: we’re doing a decent sized project using a standard sort of requirements driven approach in a spreadsheet in a government agency which has mixed feelings about agile – and guess what?
Well, thanks to some discussion, people who aren’t afraid to try new things and luck, we’ve managed to start taking an approach which might be known to some of you as a word that starts with the letter “A”.

Those “in the know” know what we’re up to – because they’re the ones doing it – most other people are blissfully unaware. For those of you unfamiliar with this hugely successful approach it’s called “Agile Undercover“. One of the biggest barriers to successful agile adoption is the weight and baggage currently associated with the agile buzzwords – as soon as you say agile it instantly becomes political and messy: cowboys use it as an excuse to do “iterations” and the naysayers bring out their pitchforks; and no one listens to the poor folks in the middle who actually know what they’re talking about. This might not be the case everywhere but I doubt it’s hard to imagine.

Agile undercover is where the purists go back to basics. If you really want to “do agile” then what you’re really saying is “I want to do the important things” – this means honouring the principles and probably implementing some of the practices; the one thing we can leave behind are the buzzwords.

Real-Life War Story

Some quick context: the core internal project team includes a Project Manager (PM), Business Analyst (BA), Manager of the Web Team and me as the Solution Architect; all development will be done by a vendor – we don’t have any developers in-house so this won’t be your typical developer driven uprising.

So, here’s what happened. A friend of mine who heads up the Project Managers is keen to look into agile with some degree of seriousness; in fact he recently did a “lunchbox” session on agile – skipping most of the buzzwords but including concepts like “features”. He’s mostly coming at this from his own angle – I wouldn’t describe him as a long-time SCRUM practitioner or anything – so good on him.

“Our” PM was at the session; she’s never done agile before in her life – but she’s open to new ideas and always keen to learn new things. Awesome. The rest of the core team were in a similar position – not adverse to the idea. Timing is everything; I need to explain the point we were at in the project. There’d been a massive requirements gathering effort, after removing duplicates we managed to get down to 196 “Business Requirements”, these had then been prioritised by the wider internal project team.

The next step was to confirm to our vendor what we wanted included in the first delivery so they could estimate effort and cost for us. No problem there except going into this we had no idea what the total effort would be – would we be including too much or too little?

I suggested a SCRUM based approach – but I didn’t quite put it like that; this suggested approach was one I’d suggested earlier – probably with a view that it’d take people time to get used to the idea. This aligned nicely with our PM discussing some concerns about how the requirements and estimation process was likely to shakedown – not concerns with the vendor or any people involved – purely the process.

My suggestion was simple – let’s rank all the requirements (in terms of business value) and then get the vendor to score all of them for effort giving us a rough total cost and date. The PM (who attended the lunchbox session) wanted to group requirements into logical “features” (her words not mine). “Bring it on” I said. Boy do I have a plan for you! First we took the existing spreadsheet of requirements which looks something like
this:

The key point here is that we have 196 requirements that are broadly prioritised (90 were “critical”), we also have a column that states whether the requirement can be met Out-Of-The-Box (OOTB), requires configuration or needs custom development (this isn’t the same as an actual score for effort – but it’s a good start; if something’s OOTB then there’s not much point arguing about it regarding timescales). I then made a copy of this worksheet and fiddled with the layout until I got something that would resemble a
Story Card.

The idea is that there’s one requirement per row, and if you format it appropriately you can print one requirement per page, all you need to do then I print four pages per sheet of paper and take to them with scissors or a guillotine. The original list of requirements had a “category” column which broke the requirements into 5 or 6 categories –
they were a bit broad but helped us break the next part of the process up.

We spread all the requirements for a given category out on the table and started sorting them into logical features – things which sounded the same or would naturally fit together, things which would naturally make a unit of work. We at this stage we treated all requirements as equal – ignoring the existing priority rankings (“Critical”, “Highly
Desirable” etc). Naturally this process led to some great discussion.

Some points that came out:

  1. Don’t worry if a feature pile gets to big – until it’s scored you just don’t know, and it’ll be easy enough to break that feature into smaller parts later (did someone say iterations? Naughty! – this is undercover, remember?).
  2. Some requirements seemed better suited to feature piles from the other “legacy” categories – no worries, just add / remove them from piles as required.
  3. By flicking through a feature pile you can easily get a feel for how important it is as the existing
    requirement level priorities were plainly visible (the big red line means “Critical”).
    We needed to easily identify feature piles, so we started labelling them with a sticky note.

Pretty soon we ended up with feature piles, which we grouped by our “legacy” categories, and roughly ranked for good measure.

The final act in this immediate process was to rank all the feature piles (in terms of business value), relative to each other. At this point we numbered all the piles: 1 (most important) down to 39 (least important); that’s an average of 5 requirements per pile.

After that it was a simple matter of adding a new column to the spreadsheet thus capturing the results.

We offered our proud piles to the vendor but they chose to take the digital copy; I think that’s actually the best idea: we safeguard the “originals” and the vendor can print their own copy of the requirement cards – including any additional columns they want to use.

Next Steps

The requirements now need to be scored for effort by the implementation team (our vendor), and rather than ask them to score each feature pile for effort we’ve asked them to score each requirement – why? I hear you ask. The problem with scoring only the feature piles is that if for any reason we have to split a feature pile up we
won’t know the effort for each. The best we can do is to have a score for each requirement and thus get a score per feature pile – assuming we need to start breaking them up.

Naturally the implementers will be concerned with managing dependencies; so how best to score for effort? I know from experience that you want to score realistically but take advantage of anything you can – therein lies the danger: if they score a particular requirements effort as low based on a dependant requirement already being implemented we’ll all run into problems if we start changing the contents of the feature piles.

This is where simple common sense comes into play: the feature piles represent our current thinking as to how they should be implemented – so things are only going to change for a good reason. The build team should be able to use this knowledge to their advantage – scoring effort based on any advantage via dependencies is fine
(it helps the bottom line) but they need to let us know; likewise we need to discuss with them any changes we’re thinking of making to the feature piles.

Now we get to the second part of the pep talk I had with our PM: once we have a ranking for business value and a score for effort we can start to look at how we “phase” the work for implementation – big bang or chunks. The one (of many?) rules I suggested putting in place was that regardless of how long a “phase” is we identify scope for that and not change it once that phase starts; the time-box for the phase must not change. 

My reasoning for the fixed phase length (yes – iteration if you will) is based on the tried and true Agile practice of being able to establish history – so we get to the point of being able to say “we get through X worth of effort per iteration”, therefore we know how long the project will take overall, or how much we can do for a fixed cost. So, we’re all looking forward to see how the effort scoring goes.

Key Takeaways

  1. Avoiding Agile buzzwords helped avoid political minefields and allowed everyone (regardless of agile experience) to get involved in the process and contribute to it.
  2. Working with requirements in a tactile fashion is easily the fastest way to deal with them; there’s no bottleneck of people fighting over the mouse and working this way is very liberating.
  3. You get a good overview of the entire projects scale.

RoboMojo

RoboMojo

RoboMojo is simply a shell for calling Microsofts robust file transfer tool: ROBOCOPY.  You can get it (either the program itself in a stand alone MSI installer, or the source code) from http://robomojo.codeplex.com.

RoboMojo let’s you set-up “Tasks” that you can get ROBOCOPY to do – avoiding the need to enter complex arguments everytime (and get them wrong – after all, to err is human).

With RoboMojo you can also set-up “Jobs” which are collections of tasks.


Before You Start

RoboMojo uses settings configured in the RoboMojo.config file.  The three settings to verfiy are:

  • Morphological.RoboMojo.XmlDataProvider.NameAndPathOfDataFile – specifies where your RoboMojo Jobs and tasks are saved.
  • Morphological.RoboMojo.XmlDataProvider.PathOfDataFileBackups – specifies where back-ups of your RoboMojo Jobs and tasks are saved.
  • Morphological.RoboMojo.TaskExecutorMSRoboCopy.LocationOfRoboCopyEXE – specifies where the ROBOCOPY.EXE file is on your system.  The default setting should work for most users.

Using RoboMojo

RoboMojo has one main screen, with three tabs.

  • Run: used to run Tasks or Jobs
  • Edit: used to manage your RoboMojo Jobs and Tasks
  • Options / About: self explainatory

The RoboMojo Jobs and Tasks you create are stored by RoboMojo, currently the only option for this is as a text file.  It’s called RoboMojoState.txt, and by default is kept in the RoboMojo folder.

Shortcut for Copying RoboMojo Tasks

On the Edit tab, drag an existing Task onto a Job in the main tree control, this will create a copy of that Task on the target Job.  The “Edit Task” part of the UI will populate with the details of the Task – beware that the new Task needs to be saved before selecting a different Task or Job.
Issues / Things to be Aware of

You can change the “theme” of RoboMojo on the Options tab, but the theme only applies to the main window, and it won’t persist if you close RoboMojo.  This feature will be completed in a future release.

The XML Data Provider likes to make a back-up copy of the RoboMojo data file (RoboMojoState.txt) wheneever you make a change.

All RoboMojo Tasks have a “TaskOrder” property; at the moment you can’t edit this via the UI – you’ll have to dive into the RoboMojoState.txt file and change it manually.
Using ROBOCOPY

Beware of calling ROBOCOPY tasks that write to special areas of the file system (like “Program Files” in Windows7) – if ROBOCOPY fails the ROBOCOPY cmd window will disappear realy fast (before you can read the error message.  The best way to deal with this is to get ROBOCOPY to write a log – this is one of the many options you can give to ROBOCOPY.

See the “Robocopy Options.txt” for more info, or manually invoke ROBOCOPY from a cmd prompt with the argument /?  I’ve also found this very useful PDF (http://theether.net/download/Microsoft/Utilities/robocopy.pdf).
Licence Stuff

  • RoboMojo is free and open source software (but not the ROBOCOPY.EXE itself which belongs to Microsoft) and is released under the Ms-RL.
  • The icon used is by Forrest Walter (www.forrestwalter.com/icons).
  • The full licence is provided in Licence.txt.  Contributions welcome, for more info see: http://robomojo.codeplex.com

5-Layer Architecture

5-Layer Architecture

This is the homepage for what I’m calling the 5-layer Architecture.  The current version (0.2) is my first public draft.  My reasons for doing this are (at least partially) covered in the document.

The current PDF is 33 pages long, with some supporting diagrams.  My intention is to expand on this by including code examples, and providing one or two “quick start” / cheat-sheet type reference documents to make it more accessible.

Any feedback is of course warmly encouraged and most welcome; email me at: adriank [at] morphological [dot] geek [dot] nz

Quick Introduction

The 5-Layer Architecture reflects “real-world” work that I have been involved with since around 2003.  This work is mainly ASP.NET based; so you might also refer to it (if you feel so bold) as a “Classic ASP.NET Architecture” – classic in the sense that it seeks to describe architectural work I have seen repreated in many solutions over the last few years, and work I have seen discussed in articles and blog posts on the net for some time.

So I’m not claiming anything particularly “new” here; what I am claiming is a “bundling-up” and formal description of architectures I have seen and agree with, specifically including rules and principles that will help designers and developers make informed decisions.

It’s my hope that this work will be of particular use to developers new to architecture or considering moving into architecture more fully.

The 5-Layer Architecture is primarily concerned with the logical and physical partitioning of code into packages which support reuse.

As you can see from the diagram below, it partitions the system into (surprise!) 5 Layers.  Unlike a lot of other architectures that focus on the “main horizontal” layers (like the UI, BL and DAL) the 5-Layer Architecture formally recognises other parts as a logical layer that deserves equal recognition.  Please read the formal description (link above) for a full and proper introduction.

Logical Layers and Key Components

Logical Layers and Key Components

Morphfolia Tutorial: the ‘Bare Bones’ PageLayout

Morphfolia Tutorial: the ‘Bare Bones’ PageLayout

PageLayouts are a key extension point for Morphfolia; in this article we’ll introduce how to build a PageLayout by looking at the absolute bare minimum you have to do to get one un and running, line by line. The Morphological.Kudos project (part of the standard Morphfolia relase) is a library of PageLayouts, it serves both as an SDK and it is actually used ‘in production’ on morphological.geek.nz. My only regret with the current release of Kudos (v2.4.1.0) is that some of the code is a bit old and hasn’t been refactored to a high degree of polish; it certainly works – but it’s not as clear and clean as it could be. If you want the ‘definative’ guide to build PageLayouts then this article is the place to start.

First, we have the using statements and namespace declaration – nothing terribly complex about that. You can namespace your layouts anyway you like, but it is a good idea to think about this carefully in advance – any subsequent refactoring of the namespace will affect users who are actively using the PageLayout.

using System.Web.UI;
using System.Web.UI.WebControls;
using Morphfolia.Common.BaseClasses;
using Morphfolia.Common.Info;
using Morphfolia.PageLayoutAndSkinAssistant;
using Morphfolia.PageLayoutAndSkinAssistant.Attributes;

namespace Morphological.Kudos.Layouts
{

the class declaration is fairly standard, but there are a couple of things you need to do:

  1. Decorate the class with IsLayoutWebControl attribute (found in the Morphfolia.PageLayoutAndSkinAssistant.Attributes namespace).
  2. Inherit from Morphfolia.Common.BaseClasses.BasePageLayout
  3. Finally, its good practice when developing WebControls to include the System.Web.UI.INamingContainer interface.

Stricly speaking we don’t need to worry about INamingContainer as this PageLayout isn’t going to be functional (it won’t hold controls that need to do PostBacks, etc). Generally speaking the PageLayouts are used as templates for serving content not applications – but they can.

Decorating the class with IsLayoutWebControl means that the PageLayout will be available to users when adding and editing pages.

[IsLayoutWebControl]
public class BareBones : BasePageLayout, INamingContainer
{

This ‘BareBones’ example is going to be very basic; we’ll display the page title and content, only. In order to implement this we’ll declare a couple of controls to display the information – a Literal into which we’ll put the page title (formatted as a heading), and a Panel to hold whatever content is assigned to the page. Obviously you can put whatever you want in here – the specific controls used are relevant only to your PageLayout and aren’t required specifically to get the PageLayout working.

private Literal pageTitle;
private Panel contentPanel;

This next property is required by the base class (BasePageLayout). It allows callers to pass in WebControls for inclusion in the PageLayout, for example a site map, search results or tag-cloud. How you implement the property is up to you, but this is what I would normally do.

private Morphfolia.Common.WebControlCollection childControls;
public override Morphfolia.Common.WebControlCollection ChildControls
{
    get{
        EnsureChildControls();
        if( childControls == null )
        {
            childControls = new Morphfolia.Common.WebControlCollection();
        }
        return childControls;
    }
    set{
        childControls = value;
    }
}

Next we have the contructors: the standard arguement-less one, and one that can take a WebControl. You can dispense with the constructors if you wish, although you will need them both if you want to pass a WebControl straight in.

public BareBones()
{
}

public BareBones( WebControl childWebControl )
{
    ChildControls.Add( childWebControl );
}

One of the main reasons the PageLayouts exist is to support custom-properties – to enable end-users to be able to configure their pages how they want them. Here’s an example CustomProperty – in this case it allows users to set a width, which will control how wide the content is.

Currently the admin UI allows any text-based input, however, you can type custom-properties any way you like – all you need to do is validate the user input (which we’ll cover soon).

A CustomProperty is any ‘normal’ class property that is decorated with the IsCustomProperty attribute, it can be called whatever you like (subject to normal language restrictions). In addition to the IsCustomProperty attribute are several other attributes that provide metadata to the system, which drives the UI provided to the user when they work with the PageLayout whilst setting up a page.

What these additional attributes are, and what they do, should be self evident. All the attributes you see here take a string arguement, which is simply the value you want to assign (e.g: PropertyFriendlyName = “Content Width”). The Morphfolia.PageLayoutAndSkinAssistant.Attributes namespace provides a couple of classes (such as SuggestedUsageNotes and Descriptions) which contain pre-defined messages for some of the CustomProperties commonly used.

I’ve used plain text in this example, but you’re better off defining some constant values for consistency, especially if you’re going to develop a comprehensive PageLayout library.

private Unit overalWidth = Unit.Pixel(650);
[IsCustomProperty,
PropertyFriendlyName("Content Width"),
PropertyDescription("Use this property to set the width of the content area."),
PropertySuggestedUsage("Fixed width in pixels (e.g: 220px) or a percentage (e.g: 50%).")]
public Unit OveralWidth
{
    get{ return overalWidth; }
    set{ overalWidth = value; }
}

Defining content-containers (places for the user to assign content to the page) is pretty much identical to custom-properties: a ‘normal’ property decorated with the appropriate attributes, and it can be called whatever you like (subject to normal language restrictions). There are three attributes you can use, but only IsContentContainer is required. ContentContainerDescription allows you to describe what the content container is for (main content, navigation, footer, and so on) and ContentContainerColour allows you to color code the content containers – useful if you have a few. When the content container is displayed in the edit page UI (for users to assign content) the background of the content container is colored as per this setting (otherwise it’s a pale blue).

private string userContent = " ";
[IsContentContainer,
ContentContainerDescription("Main page content."),
ContentContainerColour("#ddeeff")]
public string UserContent
{
    get{ return userContent; }
    set{ userContent = value; }
}

If you provide a ‘Current Layout Icon’ you can indicate to the user what the selected PageLayout will look like and give visual clues as to how the content will be layed out; this icon is simply an 100 pixel square JPG which is optional – but strongly recommended. Here are some example PageLayout icons. The name of the file is based on the full type name and assembly name, syntax: “[type name], [assembly name].jpg” e.g: “Morphological.Kudos.Layouts.QuadPageLayout, Morphological.Kudos.jpg”

A simple PageLayout implemented as a 3 column table.
A PageLayout consisting of a table with 2 rows and 2 columns.
The PageLayout for a Blog: it has one content container that sits under the main blog area.
A space for content under a picture with properties.
A table with 10 content areas, all color coded for ease of content assignment in the admin section.

The FormTemplatePresenterType property defines the FormTemplate provider to be used by the PageLayout. This property is not required by the PageLayout base class but it is needed if you want to display FormTemplate structured content.

FormTemplate providers deserve documentation of their own (which will be forth coming), in a nutshell: FormTemplate Providers allow you to display structured data – as formatted by the provider, this is useful for lists or collections of things. I use a FormTemplate Provider to render items on my Product Backlog.  Normally content is input and stored as raw HTML (via the WYSIWYG editor), but you can also input structured content via a form; the user input form is generated automatically based on a simple XML file – you can have as many of these as you like.  All the XML file has to do is confrom to the simple FormTemplate schema.

When a user enters content via a FormTemplate the resulting is content is stored as XML; then when the page is served it is presented (i.e: formatted) via the specified FormTemplate Provider rather than being simply inserted into the output stream as raw HTML.

private string formTemplatePresenterType 
    = "Morphological.Kudos.FormTemplatePresenters.LivewireProblem, Morphological.Kudos";
public override string FormTemplatePresenterType
{
  get
  {
      return formTemplatePresenterType;
  }
  set
  {
      formTemplatePresenterType = value;
  }
}

Anyone who has built WebControls will be familiar with the CreateChildControls method – it’s where the majority of the WebControl is usually constructed. We don’t have to do anything specific here as far as a PageLayout is concerned, but it is the best place to start constructing the WebControl. As you can see – this example doesn’t require much work, we just need to instatiate a Literal for the page title and a Panel for the content.

protected override void CreateChildControls()
{
    pageTitle = new Literal();
    Controls.Add( pageTitle );

    contentPanel = new Panel();
    Controls.Add( contentPanel );
}

InitializeContent is a method we have to implement for a PageLayout to work, it’s where the PageLayout receives the content to be displayed and inserts it into the correct place in the PageLayout. In this example the PageLayout has only one content container so teh work we do here is fairly trivial, however, you could have multiple content containers to assign content to and you could also incorporate additional logic regarding the location and presentation of it if you wanted to.

public override void InitializeContent()
{
    EnsureChildControls();

    string propertyType;
    int temp;

    if (CustomProperties != null)
    {
        for (int i = 0; i < CustomProperties.Count; i++)
        {
            propertyType = CustomProperties[i].PropertyType.PropertyTypeIdentifier;

            if (propertyType.Equals(
    Morphfolia.Common.ControlPropertyTypeConstants.PropertyTypeIdentifiers.CONT))
            {
                temp = GetContentInfoIndexById(int.Parse(CustomProperties[i].PropertyValue));
                if (temp != Morphfolia.Common.Constants.SystemTypeValues.NullInt)
                {
                    AddContentToContentContainer(tdContentContainer,
                        Page.ContentItems[temp].ContentEntryFilter,
                        Page.ContentItems[temp].Content);
                }
            }
        }
    }
}

Let’s review the important statements. EnsureChildControls() ensures that the CreateChildControls method has been called. In this implementation we are going to insert content into the anticipated control structure of the PageLayout – if it’s not there the process will fail. You could use the InitializeContent method to get the content only – and not affect the control structure then you don’t need to call EnsureChildControls, but you’ll need to do this eventually and this is generally the right place to do it.

if (CustomProperties != null) simply ensures that we have some information worth continuing with.

propertyType = CustomProperties[i].PropertyType.PropertyTypeIdentifier; is where we grab the Property Type of the CustomProperty so that we can ensure that only ‘content’ is added; that check is the next line of code – the if statement:

if (propertyType.Equals(Morphfolia.Common.ControlPropertyTypeConstants.PropertyTypeIdentifiers.CONT))

The PropertyTypeIdentifiers class has constants that help keep the types of CustomProperties consistently defined.

All the content for a page is provied as a single collection (a ContentInfoCollection object), the problem is that this content by itself has no knowledge of where in the page it needs to go – because pages and content are loosely-coupled; the way they are coupled is via a collection of CustomProperties which includes not only all the content / content container ‘bindings’ but also all other CustomProperties as well.

The GetContentInfoIndexById method helps us arrange the content for the page correctly. Given the id of a content item (which is stored in the CustomProperty collection items as the PropertyValue property) the GetContentInfoIndexById method will scan the associated content collection (the underlying ContentInfoCollection object) and get the matching content item.

The code temp = GetContentInfoIndexById(int.Parse(CustomProperties[i].PropertyValue)); ensures that the content item was found, as we only want to add content we know should be there. If the result is equal to Morphfolia.Common.Constants.SystemTypeValues.NullInt we know that the content item we were looking for is not present in the ContentInfoCollection – e.g: the ContentInfoCollection and CustomPropertyCollection are out of sync.

Finally we call the AddContentToContentContainer method which performs the actual job of inserting the content where we want it.

AddContentToContentContainer takes three arguements:

  • contentContainer – the control that we want to append the content to.
  • contentEntryFilter – the content entry filter specifies how the content was entered and how it should be presented – see FormTemplates.
  • content – the content to add.

As mentioned earlier, content can be input as raw HTML or via what’s known as a FormTemplate, in which case the content is structered as XML. The AddContentToContentContainer method will append the raw HTML to the target control – or if the content is XML it will use a FormTemplate provider to present the content appropriately and append it to the target control as a WebControl.

The SetCustomProperties method is virtually identical in general purpose to the InitializeContent method – except that it deals with all the CustomProerties that aren’t content bindings.

The private CustomProperties field holds the internally used CustomPropertyInstanceInfoCollection which holds all the CustomProperties passed into the PageLayout. You don’t have to have this field but it’s a convenient way of working with the CustomProperties passed in.

Just as with the InitializeContent method, SetCustomProperties is usually used to accept the CustomPropertyInstanceInfoCollection passed in and use the contained values to ‘configure’ the PageLayout.

The CustomProperties passed in will typically contain values applicable to formatting (widths, colors, alignments and so on) but it can contain pretty much anything you want.

As with the InitializeContent method we call EnsureChildControls to ensure the expected control structure in instansiated.

Once we’ve established that the customProperties are worht working with we get to the heart of the method; first we get hold of the propertyKey and propertyValue. I then typically have a switch statement that evaluates the propertyKey, and for each propertyKey I want to handle I have a branch of code that uses the propertyValue that comes with the propertyKey. In this example I’m only expecting a CustomProperty that sets the ‘OveralWidth’.

All propertyKeys and propertyValues are strings, but I make use of constants for any properties which get common use – to encourage consistencey, hence: Constants.CommonPropertyKeys.OveralWidth.

As the CustomProperties sub-system only deals with strings – but you typcially code aganist specifically typed properties you need to do some validation and conversion; in this example I’m taking a string value which I expect to be able to convert into a unit (to set the ‘OveralWidth’), and if it fails I set a default value – defensive programming.

private CustomPropertyInstanceInfoCollection CustomProperties = null;

public override void SetCustomProperties(
    CustomPropertyInstanceInfoCollection customProperties)
{
    EnsureChildControls();

    CustomProperties = customProperties;
    string propertyKey;
    string propertyValue;

    if (CustomProperties != null)
    {
        for (int i = 0; i < CustomProperties.Count; i++)
        {
            propertyKey = CustomProperties[i].PropertyKey;
            propertyValue = CustomProperties[i].PropertyValue;

            switch (propertyKey)
            {
                case Constants.CommonPropertyKeys.OveralWidth:
                if (!propertyValue.Equals(string.Empty))
                {
                    try
                    {
                        OveralWidth = Unit.Parse(propertyValue);
                    }
                    catch
                    {
                        OveralWidth = Unit.Pixel(650);
                    }
                }
                break;
            }
        }
    }
}

The final step is to implement the RenderContents method, this is where our WebControl / pageLayout is fianlly committed to the output stream. If you want to do any final adjustments – this method is your last chance.

The EnsureChildControls method is called – just in case. We then check the Visible property – no point doing a bunch of work if the WebControl is not going to be visible (this probably won’t matter when serving the WebControl from an HTTP Handler – but it’s good practice as you may decide to use the WebControl elsewhere). You haven’t forgotten, of course, that a Pagelayout is bascially a WebControl, have you.

The ChildControls property is not on the critical path when developing a PageLayout – but it’s very handy. The BasePageLayout class provides the ChildControls property so that callers can add WebControls to the PageLayouts; as an implementer your only real choice is what to do with them. You can ignore them completely if you wish, or far more usefully you can put them somewher in your PageLayout. You could even be ultra clever and write some logic that put different controls in different places – assuming you knew what to expect.

For this example we’re just appending any controls passed in to the sole content container. Real life examples of this property in action are where Morphfolia adds the SiteMap WebControl, Search Results, Tag-Cloud and WordIndexListPresenter WebControls. See the Morphological.Kudos.Layouts.QuadPageLayout PageLayout as another example.

The very last thing we do in this method is commit the WebControl to the output stream, by calling the RenderContents mehtod, however, just before we do that we ‘connect the final set of dots’.

The pageTitle Literal is finally given it’s value: the title of the page (wrapped up in an HTML <H1> element), courtesy of the PageLayouts reference to the current pages’ underlying implementation of the Morphfolia.Common.Interfaces.IPage interface. This is basically an object that gives us access to the basic properties of the ‘page’ (Title, PageID and so on).

Then we set the width of the contentPanel content container to the value stored in the OveralWidth variable. As I hope I made sufficiently clear earlier – we can set the values against the controls (contentPanel.Width = OveralWidth) either here or back in SetCustomProperties where we processed the CustomProperties initially.

protected override void RenderContents(HtmlTextWriter writer)
{
    EnsureChildControls();

    if( Visible )
    {
        if( ChildControls.Count > 0 )
        {
            for(int c = 0; c < ChildControls.Count; c++)
            {
                tdContentContainer.Controls.AddAt(c, ChildControls[c]);
            }
        }

        pageTitle.Text = string.Format("<h1>{0}</h1>", base.Page.Title);

        contentPanel.Width = OveralWidth;

        base.RenderContents (writer);
    }
}