Showing posts with label ubiquitous language. Show all posts
Showing posts with label ubiquitous language. Show all posts

4/02/2009

PropertyFor Sale

Properties. And, Java. Lots of languages really, but let's look at Java. Every Java (and other langs too) application of any size is going to be using some properties. Typically, they'll be held in a "myspecializedvalues.properties" file, but not necessarily. For this example, let's assume you are using such a file (and can then thus use Java's built-in property management mechanism), but again, its not really the point. And this approach can be applied no matter what format you choose to store your properties.

The point of this is to show you a better way to manage - a better way to encapsulate and access - your properties so that the implementation is hidden behind an expressive interface, easy for anyone to understand and use.

The point is to show the PropertyFor class, and to tell you why its better than what you probably have in place.

So, this example has a strategy factory class that needs to make its decisions based on a property setting, this property having a true/false (boolean) value. It starts off looking like this:
public class GeneratorFactory {
public String propFileName =
"ELearningSettings.properties";

public GenerationStrategy projectGenerationStrategy() {
if (shouldIgnoreCode())
return new GenerateWithoutCode();
else
return new GenerateWithCode();
}

private boolean shouldIgnoreCode() {
Object valueObj = getProperty("CODE_IS_USELESS");
if (valueObj != null)
return Boolean.parseBoolean((String)valueObj);
return false;
}

private Object getProperty(String key) {
Properties properties = new Properties();
try {
properties.load(new FileInputStream(propFileName));
} catch (IOException e) {
throw new RuntimeException(e);
}

return properties.get(key);
}
}

You'll hopefully notice something about this factory. First, it's primary responsibility is to serve up the correct strategy to its caller. Of course though, you'll also notice that not only does this class do its primary purpose, but it also has a lot of low-level knowledge about how to obtain the information it needs to make its decision. It knows all sorts of things about icky java property mania.

Now, if this is the lone property in your system, than maybe this is okay and doing any kind of extraction here might be YAGNI (you might though, even if that is the case, be bothered by that fact that this class clearly violates the SRP, nonetheless...).

Of course though, this is not the case, and so let's assume that although this is the only class you see in this example there are in fact more properties in your system and more users of them.

So, the logical thing to do is to extract that property reading management into its own class, happy to have its sole responsibility being providing property values. You do so, and end up with this new "Settings" class:
public class ELearningSettings {
public String propFileName =
"ELearningSettings.properties";

public Object getProperty(String key) {
Properties properties = new Properties();
try {
properties.load(new FileInputStream(propFileName));
} catch (IOException e) {
throw new RuntimeException(e);
}

return properties.get(key);
}
}

public class GeneratorFactory {
public GenerationStrategy projectGenerationStrategy() {
if (shouldIgnoreCode())
return new GenerateWithoutCode();
else
return new GenerateWithCode();
}

private boolean shouldIgnoreCode() {
Object valueObj =
ELearningSettings.getProperty("CODE_IS_USELESS");
if (valueObj != null)
return Boolean.parseBoolean((String)valueObj);
return false;
}
}
You slap five with your pair and check in, this is much better! Now your factory can do it's job without having any internal worry about where the settings (properties) are really coming from or how they're implemented. Any other users of properties also get the same luxury. A big improvement, no doubt.

Many systems I've seen have figured this much out, and have this in place. A "Settings" class that hides the details of how to look up properties, all you have to give it is the key to the property you want.

But, this has limitations.

First, and as many will figure out and solve on their own, a sprawl of the property key strings hard-coded in the various users of the properties. You want to change this key? Have fun chasing all the uses down. Of course you could create a constants file for these keys, and have the callers only know the constants (which, in Java at least, provides the big benefit of being able to leverage you IDE when you want to change its name), but is that really enough?

Second, yes your factory doesn't know about "ELearningSettings" or the "java...Properties" guts, but it does still have the job of knowing the format of these property values ('Object' in this case) and how to turn that into what it really wants, a boolean.

Third, particularly if haven't created a constants file (in response to the first problem), how easy is it for future developers to go to one place and see all the possible properties/settings the system has available for them?

There may be more limitations, but that's enough for me.

So, our answer to each of these questions is where the magic happens, the MBark of this article. We evolve our generic "Settings" class into a domain-friendly "PropertyFor" class:
public class PropertyFor {
public static String propFileName =
"ELearningSettings.properties";

public static boolean shouldIgnoreCode() {
Object valueObj = getProperty("CODE_IS_USELESS");
if (valueObj != null)
return Boolean.parseBoolean((String)valueObj);
return false;
}

private static Object getProperty(String key) {
Properties properties = new Properties();
try {
properties.load(new FileInputStream(propFileName));
} catch (IOException e) {
throw new RuntimeException(e);
}

return properties.get(key);
}
}

public class GeneratorFactory {
public GenerationStrategy projectGenerationStrategy() {
if (PropertyFor.shouldIgnoreCode())
return new GenerateWithoutCode();
else
return new GenerateWithCode();
}
}
What did we do here? Well, we've taken all the knowledge highlighted above as our limitations and removed it from our factory (really, from all of the users of settings), and put it into our "Settings" class - which, as a result, now becomes a more useful, expressive PropertyFor utility.

So, you'll see our factory now has to worry just about choosing a strategy, and no longer has any overhead related to obtaining the values it needs to make its decision. More specifically, it doesn't know where the settings come from, doesn't know the details of how to access them or the keys that identify them, and it doesn't know what raw format they come in. The factory knows it needs the boolean value of whether or not to "ignore code", and it gets that in one clear, simple line of code.

Further, you've got the beauty of expressive methods on singular class to be very domain-centric in assisting other programmers to access the available setttings/properties for your system - these methods, not only being clearly and expressively named, but also being typed appropriately for ultimate ease to the consumer. And of course, when you need to change the name of the setting and/or the name the callers know it by, no problemo.

So, that's really the main meat.

For good measure though, we take a moment to improve the design of our PropertyFor class. First, this isn't the only boolean setting we have (use your imagination) so we should have a nice clear reusable method to handle our boolean typed settings:
public class PropertyFor {
public static String propFileName =
"ELearningSettings.properties";

public static boolean shouldIgnoreCode() {
return boolanValueFor("CODE_IS_USELESS");
}

private static boolean boolanValueFor(String key){
Object valueObj = valueFor(key);
if (valueObj != null)
return Boolean.parseBoolean((String)valueObj);
return false;
}

private static Object valueFor(String key) {
Properties properties = new Properties();
try {
properties.load(new FileInputStream(propFileName));
} catch (IOException e) {
throw new RuntimeException(e);
}

return properties.get(key);
}
}


And then, it really is pretty inefficient of us to read the properties file over and over, so let's take care of doing that just once and being done with it:
public class PropertyFor {
public static String propFileName =
"ELearningSettings.properties";

private static Properties properties;
static {
loadProperties();
}

private static void loadProperties() {
properties = new Properties();
try {
properties.load(new FileInputStream(propFileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static boolean shouldIgnoreCode() {
return boolanValueFor("CODE_IS_USELESS");
}

private static boolean boolanValueFor(String key){
Object valueObj = properties.get(key);
if (valueObj != null)
return Boolean.parseBoolean((String)valueObj);
return false;
}
}
So there you have it: PropertyFor.

And, of course, this isn't a post about TDD, but here is the test that was in place and passing before and after any of these refactorings went down:
public class GenerationStrategyFactoryTest {
@Test
public void needingACodelessStrategy() {
propertiesFileIs("CodelessGenerationStrategy");
assertTrue(strategy() instanceof GenerateWithoutCode);
}

@Test
public void needingACodeStrategy() {
propertiesFileIs("IncludeCodeGenerationStrategy");
assertTrue(strategy() instanceof GenerateWithCode);
}

private void propertiesFileIs(String fileNameBase) {
String filePath = "testdata/"
+ fileNameBase + ".properties";
PropertyFor.propFileName = filePath;
}

private GenerationStrategy strategy() {
return new GeneratorFactory().
projectGenerationStrategy();
}
}
As an exercise, go ahead and write the test you think I have for the PropertyFor class, because of course you know I do!


ps// I'm really not liking this code highlighter library so far. Any other Bloggers have good suggestions for a good library?!?

3/27/2009

Killing "Quality"


So, a guy walks into a bar...

No, just kidding. But seriously though...

You walk into a bar and order a "low quality" beer (tough economy these days). What does this mean to you? That it'll come out with a bug swimming in it? That it will be served heated up? That it will be skunked? Glass only half full?

No, of course not. You'd be appalled, outraged. Have every right to ask for your money back. This place has acted in bad faith, they've acted unacceptably. You leave angered and vow to never return.

Your wife wants you to drop $600 on a new Louis Vuitton bag (you gotta buy cheap beer and she' still asking for Louis?!?), because it's a "top quality" product. Does she describe it this way because she knows it has less likelihood of falling apart the minute she gets it, or its colors smearing, or it having holes in the bottom? Again, no. These things are assumed to be absent. In the rare case you do happen to find anything like this, you are sure to invoke "return to sender, no questions asked".

I could continue on this way throughout various types of products, but I suppose you get the point.

Well, this ain't the case with our industry (Software Development). So I ask ye: WTF, man?

We use the word "quality" as an indicator of both "value" and/or "defect" presence, interchangeably.

When someone says "high quality" they could very well be talking about the absence of defects or they could be talking about the presence of value. And by software standards, neither would be an inappropriate use of the word.

Not so in the bar, not with your beer. Why then for us? Again I ask, WTF?

I know, I know. Some of you are sitting there saying (correctly), "hey, wait, agile pays attention to customer feedback to iterate towards a higher quality solution. We're talking about 'value presence' there." Or maybe your saying, "Our company's website says 'highest quality product in the industry!'. That's talking about 'value presence' too! That's what we mean when we say 'quality'."

Well, maybe so (and good for you, seriously). But I bet many of you still call your testers "the QA folk". "QA", as in Quality Assurance, as in "Those who ensure quality". But really, is their (primary) function that of ensuring 'value presence', or of ensuring 'defect absence'? Look, don't get me wrong, on a healthy agile team these wicked cool cats ARE involved in 'ensuring high value', but at the end of the day that isn't why you're calling them "QA'ers".

I've seen my share of "quality review" meetings, or fancy charts of "quality metrics", or annual budgets that talk of "quality goals" ... where in each of these cases, "quality" is talking about DEFECTS.

When was the last time someone described the benefits of TDD without mentioning, excitedly, "increased quality"? (And, yes indeed, I am certainly just as guilty as the next guy.)

So, why do I care? Why the rant?

Because, it's an indication of the generally absurdly high level of tolerance our industry has for defects.

That we describe defect density with the same word that we use to describe product "value" (to our customer/consumer) is gross.

Heck, I'd go as far as to say its a part of the reason that we have such a generally high tolerance in the first place. It's confusing and it is misleading. It's too easy to masquerade our defect problems as a "quality improvement initiative" or some other politically wimpy label.

When our customers get a bunch of "bugs in their beer" why aren't they appalled and outraged? Why aren't we? Why don't they storm out and vow to never come back? Why is it so damn okay to have defective software? For the third time, WTF?

Don't get me wrong, I'm not saying we should have an absolute "zero defect, period" attitude, that's simply unrealistic considering what we do. But we should have a low enough tolerance for defects that it makes no sense for us to use the word "quality" when talking about them.

"Quality" should be used as a measure of functional/aesthetic utility to our consumer, and not as a measure of defects. Really, it should just be assumed that defects are generally absent. This should just be implied in what it means to be a Professional.

So:

I hereby propose we as software professionals and businessmen stop using the word "quality" to mean a "measure of defects".

Well then, what word will we use? I polled Twitterverse with this question and received lots of great responses, but the group's choice as winner, courtesy of one Brian "Big Ball Of Mud" Foote, is this:
Shittiness.

Software with minimal defects has a "low degree of shittiness"; lots of defects means it has a "high degree of shittiness".

Of all the tweep responses though, overall my very favorite was from Lisa Crispin who said, "I have never liked measuring defects so it's hard to think about what to call it."

Nice, now that actually says it all. Something tells me that Lisa's company does not simply think of their testers as "the QA folk". There is hope!
 
/* */