Thursday, February 28, 2008

Wise Tip #1

(as in Wise Installer of course)

I learned something new about relative paths in Wise, thought you might find it useful.

When you're working on an installation package in Wise Installer, it remembers the location of the source files you added, so that you can quickly recompile the package whenever one of the files changes. Usually convenient, but there a couple of cases where this causes problems.

  1. You branch the project to a new milestone and now it's in a folder named "Milestone2" instead of "Milestone1" (You are using milestones in your project, right?)
  2. You're working with another developer who doesn't have the exact same folder structure as you.
One solution is that everyone working on the project should have identical folder structures. In general, this is a good idea and can eliminate confusion on the development team. Our SourceSafe databases are mostly structured in a Client Name/Project Name format that seems to have worked well for us over the years, and a lot of us have set up our systems to use D:/Projects/Client Name/Project Name.

But sometimes this isn't practical. For instance, some folks don't have a "D:\" partition for project files, so they have to use "C:\Projects" instead.

The solution

Wise has another solution for us: Select Tools menu > Convert Source Paths. This lets you clean up the paths to all of the source files you added.

The trick is that you can define all paths to source files relative to the location of the WSI. So the best option is to put the .WSI in the root folder of your project. That way, all of your project folders are automatically relative, e.g. .\Model, .\Storage, .\System, .\Template, .\Working.

As you branch to new milestones, the .WSI comes with you. You're probably updating the version number or adding new files anyway, so modifications to the .WSI would also be expected in the new milestone folder.

Hope this works for you!

Thursday, February 14, 2008

YAGNI

"You Aren't Gonna Need It."

We don't use this term much in our offices, but maybe we should.

YAGNI comes from the Agile / Extreme Programming (XP) development mindset. The idea is that for every feature request or "cool idea" that you or your manager or your customer might come up with, you ask yourself:
  • Do I really really need this now?
  • If you're sure you really really need this right now, then do it.
  • If you're considering it because you think there's a chance you might need it later, don't do it!
Sounds simple, right? Don't build code that you don't need right now. Or more accurately -- don't build code that does not serve to satisfy your customer's need right now.

But how often are we tempted to add in "cool ideas" to our models and projects? Or how often do we come up with a super-abstract "generic" version of something that we might need one day for another scenario?

Perhaps we add in a lot of output statistics to our model that we may think somebody will be interested in seeing one day. Or we quest for the ultimate generic reusable flexible abstract module for X (sorters, process flow, trains moving, etc. etc. etc.) that we know we're going to need for some future project that we may sell someday.

That's what YAGNI is for. It trains you to resist this temptation. Focus on the code that you need right now. Focus on the deliverable that you promised to your customer right now. Everything else can likely be put off until a later milestone - if at all.

Do you really really need this now?

Originally this principle was targeted at programmers who would try to put their computer science education to work unnecessarily -- designing complex object hierarchies, layers of abstraction, "generic" versions of functions that would work with future to-be-determined classes.

For example, Ron Jeffries, one of the founding fathers of XP, writes:
You find that you need a getter for some instance variable. Fine, write it. Don’t write the setter because "we’re going to need it". Don’t write getters for other instance variables because "we’re going to need them".
Sometimes I am in the habit of writing getters and setters for my private member variables in my AnyLogic Java classes. But why am I spending the time to do this? Because I might need it someday?

YAGNI.

Balance

YAGNI is different from "don't design anything" or blindly ignoring all feature requests from your project manager / creative team / customer. You definitely want to make sure you're looking at the big picture, knowing the end goal of your simulation model or software project.

There are other concerns you need to balance where you may choose to write code that initially seems unneeded: things like refactoring for readability, or designing for upcoming (known) milestones. And it's certainly good practice to design (and comment, and code) as if someone else might reuse your code someday. Reusability is good in this sense.

For example, this article talks about a developer who implemented serialization of his objects to flat files, because it was the fastest and easiest approach to get the milestone done. The problem was that in the very next milestone, these objects were supposed to be serialized to a database, and the mechanisms to write to that database had already been developed. By focusing blindly on what he considered to be the simplest way to solve the problem, he created additional work for the rest of the team down the road to rewrite his ostensibly "simpler" version.

That's Bad YAGNI.

The Big Bad COM Scenario Manager

On one of the intermediate releases of the Excel UI, Jonathan (whom some of you may remember) and I developed a super-abstract version of the Data Set Manager.

It had COM interface classes neatly separated from its implementation classes so that we could re-implement data set management within a different application if we ever wanted to. At the time we had been experimenting with Microsoft Access-based solutions, and we thought we might need to migrate our data set management utilities into Access VBA.

It had custom type-safe collection classes instead of native data structures so that we could use our DataSet class in other projects if we ever wanted to. At its core, a DataSet is just a zipped up collection of files, something we'd probably want to manage in other projects.

It separated the zip utility library functions from scenario management functions so that we could use the zip library independently in other applications if we ever wanted to.

It was a textbook approach toward good COM development techniques.

It was also totally unreadable and unmaintainable. Completely over-designed. When a bug popped up, it could take hours just to trace through all of the layers of abstraction to figure out what was going on. If I ever asked our dev team to investigate an open bug in the Scenario Manager, they'd immediately find 5 excuses as to why they were too busy with other project work.

Last year I finally bit the bullet and refactored this back into a single ScenarioManager assembly in the current Modeling Studio. We got rid of about 15 classes. Reduced it from 2 DLLs to 1. And you know what? You can read the thing now. It could be even cleaner, but it's a lot better than where it was.

You guys would still probably run scared if asked to debug it... but let me assure you that's for legacy reasons.

"Wouldn't it be cool if...?"

We're all creative folks. We have lots of cool ideas about how to make our models and applications better. Now how would you feel if your cool ideas were never ever used by a user, such that building them was actually a total waste of time?

Like this guy said:
The thought that you're (sic) really cool feature idea might be a complete waste of time takes some of the wind out of your sails, doesn't it? I know it does mine. Now imagine that you apply YAGNI to every aspiring new feature? Yeah, sort of depressing.
A recent study showed that 64% of software features are rarely or never used. (Hello, Outlook "Journal"!) That's not just some of your cool ideas -- that's most of them.

So why invest the time to write it, if you don't need it now and it may not be used anyway?

Conclusion

Geoff Skipton was the one who got me thinking about this the other day in New Jersey. In describing the temptation of feature creep, he used this analogy:

Say you're modeling a person walking from point A to point B. You could simply model that person moving between A and B.

Or you could consider the fact that there might be a puddle in between A and B, so the person needs to walk around the puddle, and they might trip in doing it so we need to capture the probability of tripping in that situation, and what if they need to stop and tie their shoe along the way, we might need to model that.....

YAGNI.

Finally, Paul B. MacCready, inventor of human-powered and solar-powered aircraft sums it up well, though he wasn't talking specifically about software at the time:
Treat every problem as if it can be solved with ridiculous simplicity. The time you save on the 98% of problems for which this is true, will give you ridiculous resources to apply to the other 2%.

"stop yagni" sign borrowed from
http://www.rimmkaufman.com/rkgblog/2007/10/16/rule-of-three/