tags:

views:

128

answers:

7

I never thought I'd have a need for anything this (since macros are bad, right?), but it turns out I do.

I find myself repeating the following pattern over and over again in my code, dozens if not hundreds of times:

object Function() {
    this.Blah = this.Blah.Resolve(...);
    if(this.Blah == null)
        return null;
    if(this.Blah.SomeFlag)
        return this.OtherFunction();

    // otherwise, continue processing...
}

I'd like to write something like this instead:

object Function() {
    this.Blah = this.Blah.Resolve(...);
    VerifyResolve(this.Blah);

    // continue processing...
}

Except the fact that the pattern contains conditional returns means I can't factor out a function. I've had to subtly change the pattern once already, and since I couldn't do a simple search it was a pain to find all the instances.

How can I avoid repeating myself needlessly, and make any future changes to this pattern easier?

A: 

It is better to extand the Blah class with VerifyResolve extantion method. If you own the Blah source then may be better to create some IVerifyResolveble Interface and make Blah implement it.

tsinik
A: 
object Function() { 
    this.Blah = this.Blah.Resolve(...);
    object result;
    if (VerifyResolve(this.Blah, out result))
        return result;

    // continue processing... 
} 
Henrik
+1  A: 

You could say something like:

object Function()
{ 
    this.Blah = this.Blah.Resolve(...);
    object rc;
    if (!VerifyResolve(out rc)
       return rc;

    // continue processing... 
} 

bool VerifyResolve(out object rc)
{
    if(this.Blah == null)      
    {
        rc = null;
        return true;
    }
    if(this.Blah.SomeFlag)      
    {
        rc = this.OtherFunction();
        return true;
    }
    rc = null;
    return false;
}
ChrisW
It's messy, annoying, and verbose, but this is what I had to go with. There's probably no better way.
zildjohn01
+3  A: 

If you often find that you have to check against null you may want to use the Null Object Pattern. Essentially, you create an object that represents the null result. You can then return this object instead of null. You will then have to adapt the rest of your code to include behaviour for the null object. Something along these lines perhaps:

MyClass Function() 
{  
  this.Blah = this.Blah.Resolve(...); 
  VerifyResolve(this.Blah);

  // continue processing...  
}  

MyClass VerifyResolve(MyClass rc) 
{
  // ...
  return rc.Blah.SomeFlag ? rc.OtherFunction() : rc;
} 

NullMyClass : MyClass {
  public override bool SomeFlag { get { return false; } }
}
Martin Liversage
Good thought, but in this case `null` is used safely and is part of the design of `Resolve`.
zildjohn01
+1  A: 

Maybe neater:

if (!TryResolve(this.Blah)) return this.Blah;

where TryResolve sets the value of this.Blah to either null or this.OtherFunction and returns an appropriate bool

Yellowfog
Wouldn't you need to pass this.Blah as a ref or out parameter, otherwise you'd only be setting the reference of the method parameter passed into TryResolve, and not this.Blah itself...
Matthew Abbott
yes, small bit of stupid there
Yellowfog
Very nice, except that I don't want `this.Blah` overwritten when I want to return. Still, +1 since you went for simplicity. I'm sick of these 20-line C# solutions that are 2 or 3 lines in every other language...
zildjohn01
+1  A: 

No offence but there's a couple of code smells in there:

this.Blah = this.Blah.Resolve(...);

This line in particular would cause me to start the process of a rethink.

The main problems I'd have issues with are the object return type and the assignment of a Property to a value returned by calling a method on that property. These both smell like you've messed up the inheritance somewhere and ended up with a heavily stateful system, which is both a bugger to test and a pain to maintain.

Perhaps it would be better to rethink instead of trying to use hacks and tricks to sidestep this issue: I normally find that if I'm trying to abuse the language with a feature like Macros then my design needs work !

EDIT

Ok, so with added info perhaps this isn't so much of a smell, but I'd still suggest the following:

class ExampleExpr{
    StatefulData data ... // some variables that contain the state data
    BladhyBlah Blah { get; set; }

    object Function(params) {
        this.Blah = this.Blah.Resolve(params);
        ....
    }
}

This code is worrying because it forces a fully state-based approach, the output depends on what has happened beforehand, and thus needs specific steps to replicate. This is a pain to test. Also, if you call Function() twice, there's no guarantee what will happen to Blah without knowing what state it was in in the first place.

class ExampleExpr{
    StatefulData data ... // some variables that contain the state data

    object Function(params) {
        BlahdyBlah blah = BlahdyBlah.Resolve(params, statefulData);
    }
}

if we use a factory-style method instead, returning a new instance with specific information whenever we are presented with a certain set of parameters, we have eliminated one place where stateful data is used (i.e. the BladhyBlah instance is now re-created on each call with a specific parameter set).

This means we can replicate any functionality in testing by simply calling Function(params) with a specific Setup() to create the statefulData and a specific set of params.

In theory this is less efficient (as a new BlahdyBlah is being created on each factory call) but it's possible to cache instances of BlahdyBlah with specific data and share them between factory calls (assuming they do not have other methods that effect their internal state). However, it's MUCH more maintanence-friendly and from a testing standpoint totally kicks stateful data's bum.

This also helps remove your original problem, as when we don't rely on an internal instance variable we can all Resolve(params, statefulData) externally from Function(params), and simply not call Function(params) if either blah == null or blah.SomeFlag == SomeFlag.Whatever. Thus, by moving this outside the method we no longer need to worry about the returns.

Hope that's somewhere in the right ballpark, it's hard to know exactly what to recommend given a small example, as is usually the case with difficult/abstract questions on here.

Ed Woodcock
Interesting thought... here's what I'm doing. I'm writing a compiler, and resolving expressions. Each expression returns either itself, or an expression to replace itself with (or null on error, for performance reasons, to avoid exceptions). For example, calling `Resolve` on a `IdentifierExpr` might result in a `SymbolExpr` referring to a variable. Do you consider this design a code smell?
zildjohn01
Also, the actual return type isn't `object`, I just used that for snippet purposes. The real return type is `Expr`. (I always avoid `object` like the plague if possible)
zildjohn01
@zildjohn01 both the obj for demo purposes and the return of null for error handling make sense (probably should have mentioned that in the Q, but my bad for extrapolating). I would still consider the use of this.x = this.x.blah to be a bit odd, almost like manually modifying the state of an object visitor-style. Perhaps some sort of static wrapper that allows you to remove the reassignment by assigning a local variable would be better from a design standpoint? I'd be loathe to suggest any specific improvements without a good idea about the rest of the code, but as a rule side effects => bad.
Ed Woodcock
Well to be honest, I consider it a bit odd too, but I couldn't think of any alternatives, and it works fine and makes sense once you understand it. The core issue is that expressions need to replace themselves, and unless I can get around that somehow, I'm hesitant to introduce any wrappers, because they'll just move the assignment somewhere else. I agree with "side effects => bad", but each expression is only referenced once, so the side effects are contained. I tried a more functional approach, and it was more trouble than it was worth. I ended up with (what I think is) a nice blend between
zildjohn01
Fair enough: What you say makes sense, however I'm not sure it's the best way to do things (I really dislike heavily stateful programs). Have you tried doing it so that you can provide a number of parameters to an expression which will always result in the same output when Resolve() is called? So instead of replacing themselves there's no single instance, just the ability to create one with the needed behaviour with a specific parameter set. ie Expression.Resolve(moreParams) as opposed to this.Resolve(params)
Ed Woodcock
Hmm, I don't think I understand... where would I get `moreParams`? I need a more concrete example -- Let's say I'm resolving `-abc`, which is a `UnaryOperatorExpr` containing a `IdentifierExpr`. As it stands now, `UnaryOperatorExpr` contains a member variable named `Operand`, which in the example is set to `IdentifierExpr(abc)`. When I call `UnaryOperatorExpr.Resolve`, it in turn calls `IdentifierExpr.Resolve`, which returns a `SymbolExpr`. UnaryOp replaces the IdentifierExpr with the SymbolExpr and then continues, knowing the type of the symbol. How would you suggest that scenario go instead?
zildjohn01
@sildjohn01 I'll try and edit to make what I'm saying more clear, please let me know if I'm off down the wrong track.
Ed Woodcock
I get what you're saying now, and you hit on the main reason I'm using a setup like this -- efficiency. I don't like the thought of creating excess class instances. I'm solving the immutability issue in a more roundabout way -- `Resolve` is actually a wrapper which calls the virtual `DoResolve`. It performs a few startup tasks, including cloning the original instance before calling `DoResolve` if the original is used multiple places. So I still have the benefits of immutability, they just come about in a different way than you might expect.
zildjohn01
The new instances are all created only as needed in one centralized place. Another way to think about it is to think of `DoResolve` as an extended constructor. I wish I could +1 a few more times, I'm enjoying discussing this, heh.
zildjohn01
A: 

It's messy, annoying, and verbose, but this is what I had to go with. There's probably no better way.

Another way is to make a struct, whose nullability is significant.

struct Rc
{
  internal object object;
  internal Rc(object object) { this.object = object; }
}

object Function() 
{  
    this.Blah = this.Blah.Resolve(...); 
    Rc? rc = VerifyResolve();
    if (rc.HasValue)
       return rc.Value.object; 

    // continue processing...  
}  

Rc? VerifyResolve() 
{ 
    if(this.Blah == null)       
    { 
        return new Rc(null); 
    } 
    if(this.Blah.SomeFlag)       
    { 
        return new Rc(this.OtherFunction()); 
    } 
    return null; 
} 
ChrisW