-
Get a monthly update on best practices for delivering successful software.
The value of wireframing even with incomplete information
The task of wireframing in application development, as I've come to know it, should begin after user research has been performed, and a complete set of requirements gathered. But what happens when, for whatever reason, you just don't have access to user research, or a full set of requirements? What if all you have are some rather unspecific, vague notions of what the user should and should not be able to do? Is wireframing at this juncture useful? I say yes. With incomplete or even almost non existent information about target users and or requirements, wireframes can still be a valuable tool in the interface designers toolkit.
The key to a wireframe's usefulness is that it is a visual document. Presumably it will be presented to one or more product stakeholders, and they will have the opportunity to review it and comment. Having something visual to respond to is one of the easiest ways to generate ideas, and identify incomplete specifications. A good assumption is that if a product's requirements are incomplete, someone at the wireframe review will notice the gap by responding in the context of the visual presentation. "Where is the Cancel button? Oh...not in the requirements? Well it's obvious that on this screen the user will need to be able to cancel, so we have to add that as a requirement."
In this way, a wireframe can be an ever evolving document, which begins by starting the requirements conversation. Of course ultimately, just prior to feature development, the wireframe should have all of the necessary specifics so that the developers can use it as a guide (along with the relevant user stories).
I've just come across Yahoo's new home page, which features a clean streamlined look, the ability to add your favorite pages as links right on the homepage, and most interestingly, a module that gives you access to (a subset of) your Facebook account. This module, which appears when you hover your mouse over the Facebook link on the let hand side of the page, will--after sign in--open up your facebook friend feed right there on the Yahoo home page.
Apparently Facebook has been giving third party websites the ability to connect to their users via Facebook for 8 months now (through a set of API's collectively called Facebook Connect). But the Yahoo home page is the most high profile example yet. This is certainly the first time I've come across it.
The benefits of Facebook connect Facebook is obvious. It'll gather more information about its users, and become more ubiquitous within the wider web, as users remain connected to its platform even while not actually on the facebook.com.
Spent some time playing around with Flash Catalyst, which was released by Adobe as a public Beta yesterday. I downloaded it today and got started on some of the tutorials Adobe labs has put up.
My impressions:
It's pretty neat stuff. I could see myself prototyping with it, although Keynote and Acrobat are my tools of choice at the moment.
From my limited time working with it, Catalyst's main function is to make it very easy to take Photoshop or Illustrator compositions and turn them into fully (front end) functional interfaces, complete with animations, transitions, fades, buttons states etc. One of the tutorials had me import artwork of a scrollbar, in 4 layers. Creating an actual scrollbar and hooking it up to a canvas was as easy as selecting the individual layers and telling catalyst which part of the scroll bar it was (up button, down button, track and thumb). It;s also super easy to connect user actions to specific screens (or states, as Catalyst calls them).
Continue reading »
Topics: Design, Flash Catalyst, Illustrator, Photoshop, Rich Interactions, Usability, uxd, Web/Tech
Another Chicago area conference coming up: FITC Chicago 2008, from June 22-23 at the Chicago City Centre Hotel & Sports Club, 300 E. Ohio. We're even supporters.
So what is it beyond the platitudinous "design and technology" event?
Obviously there's going to be lots of talk about how to develop Flex and Flash applications. Also how to develop online/offline apps with Adobe Air. Heck you'd think Adobe was a sponsor.
If designing RIA's with Flash/Flex/Air is your thing, you want to be here. It's not free, but based on last year's event, well worth the $125-$250 (depending on which sessions you go to).
Update: If you sign up here with our special ninja supporter code of PATH15, you get 15% off.
Topics: Adobe, Adobe AIR, Announcement, Conference, Design, Flash, Flex, Web/Tech
In Java, it is perfectly fine to declare an interface with static-final properties as follows:
public interface QuestionFactory
{
public static final int QTYPE_INPUT = 1;
public static final int QTYPE_RADIO = 2;
public static final int QTYPE_CHECKS = 3;
public Question createQuestion(int questionType);
}
This cannot be translated in to .NET as. The following won't work:
public interface IQuestionFactory
{
// won't work in .NET (Err: Interfaces cannot contain fields)
public static readonly int QTYPE_INPUT = 1;
public static readonly int QTYPE_RADIO = 2;
public static readonly int QTYPE_CHECKS = 3;
public Question CreateQuestion(int questionType);
}
The general recommendations in such a scenario is to externalize the const(s) in another class.
public class QuestionType
{
public const int QTYPE_INPUT = 1;
public const int QTYPE_RADIO = 2;
public const int QTYPE_CHECKS = 3;
// disclaimer: I used "const" 'cause I wanted to use it in switch/case.
// However, I assume "static readonly" could have been used as well.
}
Why is this so? The notion seems to be that interfaces cannot have states (they are stateless) and hence do not allow fields. Coming from Java world, I am not entirely sold on this argument though. I prefer one interface with all static readonly/final fields as well method-contracts (that consume those fields).
One may argue use of enum instead of int(s)... but that is a different discussion.
Topics: Web/Tech
Flash Player 9 introduced the ability to decode H.264 video format. However, it cannot encode video as H.264 (although it does encode as H.263).
This is a problem for people who want to take advantage of H.264's ability to encode at a higher quality with a lower bitrate. There are a few vendors out there who propose to offer a solution, but some of the solutions require an extra download which isn't necessarily cross platform.
With the release of AIR, Adobe seems to be targeting the Desktop market as one of their future goals. Many existing desktop applications already support H.264 encoding (see iChat for a good example). If Adobe wants to keep up with the desktop application market, it might be prudent to add support for encoding as H.264 soon.
Topics: flash player, h.264, Video, Web/Tech
I've been looking at some of the new features in the .NET 3.5 framework and have found Object Relation Mapping (ORM) very similar to IBatis.NET and NHibernate. In .NET 3.5, they use attribute based mapping between the underlying data table and entity class (Domain Object). For instance
using System.Data.Linq;
using System.Data.Linq.Mapping;
[Table="Books"]
public class Book {
[Column="Name"]
public string _Name;
[Column="ISBNNo"]
public string _isbn;
...
}
What you notice is the the class Book is mapped to a table called Books using the Table attribute and particular table columns are mapped using the column attribute on the Book class instance fields. Compared with IBatis.NET XML files; you would have to:
<sqlMap namespace="Surveys" xmlns="http://ibatis.apache.org/mapping">
<alias>
<typeAlias alias="Book" type="Namespace.Books, AssemblyName"/>
</alias>
<resultMaps>
<resultMap id="BookMap" class="Book">
<result property="Name" column="Name"/>
<result property="ISBN" column="ISBN"/>
</resultMap>
</resultMaps>
<statements>
<select id="GetBooks" parameterClass="map" resultMap="BookMap">
select name, isbn from books
</select>
</statements>
</sqlMap>
Furthermore, much of the guesswork required to create the parameterizes queries used to pull information from the database and load a collection of Book objects has been added. Simply creating a new Linq DataContext object, passing the connection string to the database and calling the generic GetTable<T> (where T is class name. in this case Book) is all you need to get the results, versus creating the individual sql in the xml file and calling one of the QueryForObject or QueryForList methods found for IBatis.NET.
Last but not least, Linq provides the programmer with built-in sql like keywords used to build expressions that sort, aggregate and limit the original result set to some more specific or limited result result set without going back to the underlying database.
Although, this is a very simplicity view of mapping a database table to .NET class. This does give you a good picture to the additional overhead required to using IBatis.NET xml file mapping versus Microsoft's Linq to Sql attribute base mapping, and demonstrates how ORM is now built right into the .NET Framework. And, you be happy to know that your .NET 3.5 Linq to Sql applications will still run on .NET 2.0 because the new features are specific to the specific 3.5 .NET compiler.
Topics: Web/Tech
After several years in Java/J2EE world, I recently started working on a .NET project. The motivation was to get to know the pros and cons of both world and leverage better ideas from each going forward.
Having used Apache Commons/Collections in Java, I longed for similar library in .NET. I am not sure if one already exists (quick google didn't turn up any result). However, considering that fact that Commons/Collections uses Callback interfaces a lot, it was clear that any such attempt would leverage .NET's "delegate" feature extensively. I couldn't resist trying to implement it myself. Here is what I ended up with.
So, in my case, I wanted CollectionUtils.collect() method, which transforms a list of object into a list of some other type of objects. This is a handy utility to unwrap/wrap an exising list into another list. So, for example, I have a List<StringWrapper> object in which each StringWrapper object is simply a wrapper around a "String" object. And let's say that I need to get a List<String> from List<StringWrapper> object.
In Java's Commons Collection I would use a call like this:
class StringWrapper {
public String a;
public StringWrapper(String a) {
this.a = a;
}
}
...
List<StringWrapper> aColl = new ArrayList<StringWrapper>();
aColl.add(new StringWrapper("x"));
aColl.add(new StringWrapper("y"));
aColl.add(new StringWrapper("z"));
List result = CollectionUtils.collect(aColl, new Transformer() {
public Object transform(Object o) {
return ((StringWrapper) o).a;
}
});
...
Here CollectionUtils.collect() would be something like (a very lame version of what is in Apache's Commons/Collection library):
class CollectionUtils {
public static <T, N> List<N> collect(List<T> list, Transformer<T,N> transformer) {
List<N> result = new ArrayList<N>();
for(T t: list) {
result.add(transformer.transform(t));
}
return result;
}
}
// Callback interface
interface Transformer<T,N> {
public N transform(T o);
}
In .NET, we could replicate this code 1-for-1 and get the same result. However, .NET's delegate keyword helps cut the fat and provides for a lean implementation as follows:
public class Collections
{
// a 'delegate' defines a method signature. Any method with same method signature can be used as callback method.
public delegate N Transformer<T,N>(T o);
// a function that takes a delegate method whose signature is declared by 'Transformer'
public static IList<N> Collect<T, N>(IList<T> originalList, Transformer<T,N> transformer)
{
IList<N> returnList = new List<N>();
foreach (T oo in originalList)
{
returnList.Add(transformer(oo));
}
return returnList;
}
}
Here, a delegate is like an abstract method and my concrete implementation could be like:
string transform(StringWrapper str) // this method's signature should match the delegate declaration
{
return str.a;
}
And the client call then becomes:
...
IList<string> result = Collections.Collect<StringWrapper, string>(listOfStringWrappers, transform);
...
Or I can do away with an anonymous delegate implementation as:
...
IList<string> result = Collections.Collect<StringWrapper, string>(listOfStringWrappers, delegate(StringWrapper str) { return str.a; });
...
Topics: Web/Tech
Be a Good Listener. We've all heard this phrase. As I experienced recently, it applies readily to pair programming as well.
I am currently helping a student learn Java while she is taking an algorithms class. Having had teaching experience in the past, I was able to teach her the basic stuff fast and well. It was mostly a one way street where I talked and she listened. As she grew more comfortable with Java, she starting asking non-trivial questions. I quickly realized that it was no longer a one way street. I had to make conscious effort to not discount what she said/asked and say what I had to say. It took us longer to arrive at a solution _together_ if I talked more than I listened. I had to resist the temptation to arrive at a solution _alone_ and bring her along; at her speed. To bring her along, I had to listen more and make an effort to understand what she understood and where she missed. This may seem counter-intuitive but I realized that it was best (in terms of code quality and long term sustainability of happy pairing relationship) when I listened to her and gave her just enough information to find her way instead of imposing my way onto her.
I understand that pairing with a newbie is distinct from pairing with your co-developer. But still, being able to align yourself to someone else's thoughts goes a long way in achieving better results.
Happy Pairing !
Topics: Web/Tech
My colleagues Matt Nolker and Shalom Sandalow have put together a nice little webinar entitled "This Won’t Hurt a Bit": Designing the Invisible Interface.. For those of us writing Web 2.0 applications, there are some key insights here, such as: "interacting with the software is not the primary goal or responsibility of the user." So when you use those nifty Ajax widgets, think about whether you are placing a usability burden on the user or are using the power of Ajax to make the interface disappear.
Technorati Tags: uxd, webinar, invisible interfaces, usability
Topics: Web/Tech
This can occur for several different reasons. For example, http://opensource.atlassian.com/projects/spring/browse/SPR-1598. Here is how I came across: Missing hibernate mapping file (hbm.xml) in hibernate SessionFactory.
When we forget to list a hibernate mapping file (*.hbm.xml) during SessionFactory creation, it usually fails fast. This fail fast happens since there is another domain-entity mapping that has many-to-one relationship with this class. However, if a given domain-entity is not being referenced by any other entity mapping file, then Hibernate (obviously) will have no knowledge that this entity-exists.
This is fine, but you expect your query to fail with proper error message when any hibernate query method is called in relation to an unlisted entity. For example, I have a User entity in addition to many other entities. For the sake of argument, let us say that no other entity refers to User entity. So, if I list hibernate mapping files (*.hbm.xml) for all entities except User.hbm.xml, SessionFactory creation won't fail. This is fine since SessionFactory has no magical way to figure out how many entity-classes should have their mapping defined and listed.
However, it should fail when I call methods like Session.createQuery("from com.package.User as s where userName=?"). You would expect Hibernate to fail-fast and complain about un-mapped class (com.package.User in this case). It doesn't. Under these circumstances, trying to execute hql query with positional parameter gives "java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based!". Trying to run query with named-param will result in 'org.hibernate.QueryParameterException: could not locate named parameter [<paramname>]". None of these errors say anything about the unmapped entity.
Related Services: Java Application Development, Custom Software Development
Topics: Hibernate, Java, Spring Framework, Web/Tech
Wow!
We just changed the model for our current big project, and it's no wonder I thought the BA Role was undefined.
I had been acting as an assistant-deputy-associate project manager, technical writer and QA Manager. Whatever the project needed, by gosh, was OK by me, and still is.
The side benefit is it makes it seem like I'm multi-talented, a very good thing come review time.
But now (drum roll please) there's a defined role for the BA.
Go figure.
In order to get the the base functionality up and working, the pragmatic approach worked very well.
But now, the client needs and wants control of the features, enhancements and repairs for the system to meet the business needs. Right up our alley.
We're moving from month-long sprints into two week sprints.
Sooooo, the first week into the current sprint, the IA and I discuss the requirements with the client for those items likely to be included in the next Sprint. We write 'em up and we frame the wires and get verbal client sign off that first week.
If it's a biggie, I'll slap a functional spec together with the IA's wire frames and work flow requirements.
If it's small, I set it in the issue tracker as an improvement with th details in the description field (I always wondered what that field was used for).
If the developers need more detail or discussions with users, I act as a liaison to get that happening without the client getting barraged by hundreds of IMs and e-mails.
I think I'm going to wish I was issued a stick.
But I gotta make that happen for the DevTeam, otherwise we can't produce what the customer wants.
The second week, I run the requirements by the DevTeam Lead for a sanity test. I'll probably flunk, but better to revise and have items really ready for the Planning Session on the second Friday.
I post the client's wish list in the wiki (can't get away from that dang tool, can I?) by Wednesday of the week before the sprint start.
It says here in The Handy Dandy Agile Methodology Handbook for the Perplexed that the developers have to read them!
In the SPrint Planning/Negotiating/Teeth-Gnashing Meeting on the Friday before the next sprint starts, the Customer ranks the items s/he wants in the sprint.
The DevTeam then huddles, makes interesting noises and then sets team estimates (kinda like liar's poker when you watch it) and commits to a list it can handle.
Me and the PM then negotiate with the Customer to come up with a final list.
We break for coffee and a smoke and then go through a Post Mortum of the sprint just ended.
Here, everyone has to talk and discuss process (not people or finger pointing- as much fun as that might be)- including the customer and his/her team. Fair's fair, right?
If an item's actionable, the PM and I will meet with the appropriate lead and figure out some mitigation strategies or process change.
Then we're off to the races for the next round.
So, the BA's role in an Agile Project isn't all that different from other methodologies.
While 'control' of the project is now in the customer's hands, defining requirements and disseminating them differs only in that we're doing 'just enough' rather than 'kill hundreds of acres of trees with Word.'
Since the developers and the customers aren't running everything through the BA or IA (typical waterfall), we loose the 'translator effect' that intrudes every time technicalese is translated to rich bidness language and vice versa.
Even so, the BA is there to help both sides meet and mesh an understanding both sides can live with and understand.
The complexity is increased with an IA on board, but that complexity is more than offset by the IA handling project foundation work like 'task flow' (work flow to us BA-types) and they can whip up wire frames faster and prettier than I can. Those benefits combined with actual design to make the end user's job easier and more intuitive is well worth the the minor complexity issue.
With that big stick, I think I want a regulation Referee's Shirt as well.
<ding> <ding>
Next Round
Powered by ScribeFire.
Topics: Web/Tech
All the fuss around LIE reminds me of my days when I was scared of NPE (NullPointerException). No matter how hard I tried, I just couldn't write code that couldn't run into NPE. Slowly, I learnt that it is not a question about not running into NPE, it is about implicit awareness about the possibility of any reference being a null at any given place and time in code. Isn't LIE very similar to NPE in that way?
Folks are afraid of switching from Hibernate 2.0 to Hibernate 3.0 because their app starts throwing LIE everywhere as soon as they do. So, instead of trying to figure out the reason for this. They switch back to 2.0.
Follow these simple rules and we can avoid LIE in most places:
Just like NPE, once we ensure that an open connection to database (hibernate session) exists whenever we deal with a hibernate managed entity, we can avoid LIE.
Topics: Web/Tech
So my first project here at PathFinder Development is to move an existing application from .NET 1.0 to 2.0. Seemed simple.
I started the usual As-Is Decomposition modeling while looking at the existing application.
It turned out to be a prototype that didn't type.
Hmmm.
OK, abandon As-Is and concentrate on To Be.
The Functional Requirements template worked just fine in Word. Everybody loved it. Everybody thought it was real snazzy. Of course it was. I'm the English Major Alice referred to in her fine blog on Design.
Everybody, that is, except our Technical Architect.
"I want you to put this on our wiki," he said calmly.
????
"And we'll all be able to edit it."
!!!!
I'm the document master on this project, Mister. I determine what the developers see and how they see it. I create the catalogs, baby. I talk to the customer, dude- keep the developers behind that curtain- they might pull out a slide rule when the suits are around. I'm the technical to business and business to technical translator, fella. I run the JAD sessions and the interviews, pal.
Well. I've only been here a coupla weeks. And they're payin' me real good. And they seem pretty smart...
So as I was groaning and moaning learning the new tool, and doing it over to the technical guy's satisfaction (who ever allowed a developer or Technical Architect to have an opinion on formatting and word use? You ever try to read one of their documents?).
And then did it again to satisfy the slave driver.
The he rubbed salt into the wound by telling me to add <previous> and <next> links at the bottom of each page.
I tricked him.
I looked at the mark-up language for our instance and found some cool tags that generated them automatically. Hah!
If I post this, I thought, and anybody on the team can edit it, what the heck do they need me for? Mebbe it's time to get the old resume revised, even though I've only been here a few weeks.
"You'll write the Functional Specifications and we'll all edit them as we develop the feature," My team-mate turned Agile Coach told me.
Oh. I'll add the use cases, data maps and controls to these 'Specifications.' Yeah, I can see how that'd work.
"No, we don't long use cases that no one will read- plop in some activity diagrams, we'll list the use cases as 'scenarios' and you read up on User Stories."
!!!
"Agile is 'just enough' documentation," he said patiently, "Read up on that, too."
$%^#@!
My hesitant, but analytical hold on the world started caving in.
None of my closely held writing, analysis or PM skills were being used, much less valued, in this Agile stuff.
It was akin to moving from the world of daily journalism into a help desk- all the moves and instincts I used in news were, at one fell swoop, totally and absolutely wrong.
Then I started to read. I like getting paid regular.
I started with the Manifest for Agile Software Development.
Not bad.
Went to the links.
Cool.
Got me some books.
Excellent.
But no mention of the need, want or value added to the Agile Team by a Business Analyst or User Experience except for some upfront JAD or interview work in Iteration Zero.
"That's because they had customer buy-in at the start with dedicated, empowered customer buy-in," The suddenly wise and no longer job threatening Agile Coach explained, "You're gonna do much of that with interaction with Subject Matter Experts and our User Experience team member as we implement this feature."
Um, How do we handle Scope Creep?
"We only deal with the feature we did last week (bug fixing), what we're working on now (design, specification and code) and what we're going to do next week," My Agile Coach explained, "And we let the visionary blog, add to the wiki in a Blue Sky section to his/her heart's content, but we only deal with that stuff as we begin designing that feature."
Mark Twain was right, your father seems like the biggest dope in the world when you're 18 and you become amazed athow smart he became in 7 years when you're 15. This turn around only took a month or so.
Ah. Thank you Sensei.
Next Up: My First Agile Project's Process Flow
Powered by ScribeFire.
Topics: Web/Tech
Business Analysts seem to come from two areas:
Coming from the second group myself, I've often been asked to help neophyte writers improve their skills. Trading writing tips for tech points is a good thing for me since I can abstract and write from today until tomorrow- but unless I understand what I'm writing about, it's more than obvious. Hence my 'quickie writer's course, the Ten Commandments to Writing Technical Requirements.
Here's the First Commandment:
You have three major audiences for and Requirements
Documentation:
Each audience has a different educational and experiential background and their own jargon.
To address each audience's needs, follow these guidelines:
1. Eliminate
jargon. You may know what SQL means,
but the VP of Order Management may not and you do not want to make that person feel inadequate nor do you really want to explain what SQL is- I usually say 'queries the database' and leave it at that.
2. Clearly
and effectively organize and label the elements of your document. We'll get into this very important area in a future blog, suffice it to say here you can get a big head start by:
- Splitting your material into logical groups your reader can easily understand
- Properly labeling each group so your reader can scan the doc to find what s/he wants.
- Use an outline- revise the outline when needed, but use it.
3. Use
consistent terms and phrases throughout the document. Don't call it 'The Application' in one are and 'The System' in another. pick one and stick with it.
4. Eliminate
buzzwords. Don't use 'initiate' when you mean 'start.' Don't use 'terminate' when you mean 'end.' And, one of my pet peeves- 'entitle' is not a fancy word for 'title.' If you are entitled to something- it means you deserve or earned it.
5. Avoid
clauses. If you need to use one, put it at the beginning, but not in the middle since the reader can't parse it that well, or end of a sentence, if you use one clause in a sentence you can put it at the end, but that should be your second choice. See what I mean?
6. Avoid
passive voice- see Commandment V. For now, just remember "Boy paints the fence" is ACTIVE voice and "The fence was painted by the boy" is PASSIVE. Note both sentences mean exactly the same thing. It has nothing to do with verb tense, it has to do with who's doing what in the sentence.
7. When
using the command form, use "must," not "shall."
"Shall" is regal and antiquated. Better yet- ignore all those 'The System must....' statements entirely and just start writing after the word 'must.'
Writing is organized thought. If you can design it, you can
write it. Write it as though you were explaining it in a conversation with your
non-technical parent. Except my mother. Ain't no way that'll happen. In such a case, you do not talk down to them,
but try to make them understand.
This is the first rule of any writing.
Next Up: Knowledge.
Topics: Web/Tech