How does it work - Expecta

##tl;dr

Follow me as I poke Expecta with a stick to see how it works - it’s pretty cool.


It’s been a long time since my last post but I thought I’d get stuck into how something that appears simple actually works. That subject will be Expecta matchers. If you don’t know what Expecta is then you might want to nip over to the Github repo and skim the Readme then we can get stuck in.

Take the following example:

expect(2).to.equal(2);

This line looks so simple but it’s hiding a lot of clever techniques that may or may not be useful to keep within your own development bag of tricks.

Let’s break this apart and demystify what’s really going on.


##expect

expect() looks like a function call, so you may assume that there is a function declared somewhere called expect. Thankfully that is not the case or this blog post would be very boring - instead we find this defined as:

#  define expect(actual) EXP_expect((actual))

this in turn is declared as

#define EXP_expect(actual) _EXP_expect(self, __LINE__, __FILE__, ^id{ return EXPObjectify((actual)); })

_EXP_expect is the actual function we was looking for.

At this point you may be wondering why did they bother with this odd chain of macro expansions. The logical reason would most likely be that expect(id actual) is an optional short hand syntax, which is only enabled by defining EXP_SHORTHAND before importing Expecta.h. Without this define you have to use the long hand EXP_expect(id actual) and this is what expands to _EXP_expect with all the additional arguments.

Go ahead and reread that last paragraph a few times if it didn’t sink in the first time.

In effect the define for expect saves you from having to type out

_EXP_expect(self, __LINE__, __FILE__, ^id{ return EXPObjectify((actual)); })

every time you want to set up an expectation.

The _EXP_expect function simply creates a new instance of EXPExpect with all the arguments supplied. I’m not going to go over the EXPExpect class as I want to cover the single line of code at the top of this post.

EXPObjectify

Before we move on though it’s worth pointing out that Expecta is really cool as it does not require you to box your arguments. It’s the EXPObjectify function that does the work of making sure that if you pass in a primitive like int, float, double, etc then it will box it with an NSValue or NSNumber automatically for you.


##to

to looks simple enough - so why is this interesting? Well knowing that it is used like this to.equal... leads us to the conclusion that it returns an instance of something that responds to equal. Before following the link to look up the definition keep in mind that to is entirely optional and I could validly call expect(2).equal(2); - this should narrow down what to returns.

@property(nonatomic, readonly) EXPExpect *to;

Yup you may have guessed it to returns an instance of EXPExpect - not just any instance but the instance it was called on - check it out:

- (EXPExpect *)to {
  return self;
}

This is just a little sprinkling of syntactic sugar. It makes the expectation read better consider expect(2).to.equal(2) vs expect(2).equal(2).


##equal

By now you are probably thinking that the interesting stuff is over and equal will just be a property declared on EXPExpect. You may also come to the conclusion that the property will return a pointer to either a block or a function so that it can be invoked with parentheses and an argument equal(2). This is exactly what is happening - kind of…

If you search the EXPExpect class you will not find a property declaration but if you follow the declarationf of equal through you’ll land in EXPExpect+equal.h, which looks like this:

#import "Expecta.h"

EXPMatcherInterface(_equal, (id expected));
EXPMatcherInterface(equal, (id expected)); // to aid code completion
#define equal(...) _equal(EXPObjectify((__VA_ARGS__)))

This is where we have to make sure our brain is really engaged and step up a gear. Take a breather and join me after the relaxing grey line…


EXPMatcherInterface ends up mapping through to

#define _EXPMatcherInterface(matcherName, matcherArguments) \
@interface EXPExpect (matcherName##Matcher) \
@property (nonatomic, readonly) void(^ matcherName) matcherArguments; \
@end

which in the case of our equal will expand to

@interface EXPExpect (_equalMatcher)
@property (nonatomic, readonly) void(^_equal) (id expected);
@end

In english this has declared a named category called _equalMatcher on the EXPExpect class. This category declares a single readonly property, which means that in the .m file we would expect to see a single method declared with the signature - (void(^)(id expected))_equal;

NB I showed the mapping of _equal as equal is only used for code completion and there is in fact never an implementation declared for - (void(^)(id expected))equal;

So being inquisitive we jump to the implementation to see how this method is defined and we find more #define magic.

EXPMatcherImplementationBegin(_equal, (id expected)) {
  match(^BOOL{
    if((actual == expected) || [actual isEqual:expected]) {
      return YES;
    } else if([actual isKindOfClass:[NSNumber class]] && [expected isKindOfClass:[NSNumber class]]) {
      if(EXPIsNumberFloat((NSNumber *)actual) || EXPIsNumberFloat((NSNumber *)expected)) {
        return [(NSNumber *)actual floatValue] == [(NSNumber *)expected floatValue];
      }
    }
    return NO;
  });

  failureMessageForTo(^NSString *{
    return [NSString stringWithFormat:@"expected: %@, got: %@", EXPDescribeObject(expected), EXPDescribeObject(actual)];
  });

  failureMessageForNotTo(^NSString *{
    return [NSString stringWithFormat:@"expected: not %@, got: %@", EXPDescribeObject(expected), EXPDescribeObject(actual)];
  });
}
EXPMatcherImplementationEnd

When the two macros are expanded we end up with this (formatting mine):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
__attribute__((constructor)) static void EXPFixCategoriesBugEXPMatcher_equalMatcher() {};

@implementation EXPExpect (_equalMatcher)

@dynamic _equal;

- (void (^)(id expected))_equal {
  EXPBlockDefinedMatcher *matcher = [[EXPBlockDefinedMatcher alloc] init];
  [[[NSThread currentThread] threadDictionary] setObject:matcher forKey:@"EXP_currentMatcher"];
  __block id actual = self.actual;
  __block void (^prerequisite)(EXPBoolBlock block) = ^(EXPBoolBlock block) { EXP_prerequisite(block); };
  __block void (^match)(EXPBoolBlock block) = ^(EXPBoolBlock block) { EXP_match(block); };
  __block void (^failureMessageForTo)(EXPStringBlock block) = ^(EXPStringBlock block) { EXP_failureMessageForTo(block); };
  __block void (^failureMessageForNotTo)(EXPStringBlock block) = ^(EXPStringBlock block) { EXP_failureMessageForNotTo(block); };
  prerequisite(nil); match(nil); failureMessageForTo(nil); failureMessageForNotTo(nil);
  void (^_equal) (id expected) = [^ (id expected) {
    {
      match(^BOOL{
        if((actual == expected) || [actual isEqual:expected]) {
          return YES;
        } else if([actual isKindOfClass:[NSNumber class]] && [expected isKindOfClass:[NSNumber class]]) {
          if(EXPIsNumberFloat((NSNumber *)actual) || EXPIsNumberFloat((NSNumber *)expected)) {
            return [(NSNumber *)actual floatValue] == [(NSNumber *)expected floatValue];
          }
        }
        return NO;
      });
      
      failureMessageForTo(^NSString *{
        return [NSString stringWithFormat:@"expected: %@, got: %@", EXPDescribeObject(expected), EXPDescribeObject(actual)];
      });
      
      failureMessageForNotTo(^NSString *{
        return [NSString stringWithFormat:@"expected: not %@, got: %@", EXPDescribeObject(expected), EXPDescribeObject(actual)];
      });
    }
    [self applyMatcher:matcher to:&actual];
  } copy];
  _EXP_release(matcher);
  return _EXP_autorelease(matcherBlock);
}

@end

Yup that’s right there are line numbers in this listing as it’s a big one.

So let’s distill what this category method is actually doing:

  1. Creating an instance of EXPBlockDefinedMatcher (line 8)
  2. Setting up blocks to enable this instance to be configured with a DSL like syntax - prerequisite (line 11), match (line 12), failureMessageForTo (line 13) and failureMessageForNotTo (line 14)
  3. Ensure that these are all initialised to nil (line 15)
  4. Configuring this instance’s properties with blocks for match (line 18), failureMessageForTo (line 29) and failureMessageForNotTo (line 33).
  5. Ensures that [self applyMatcher:matcher to:&actual]; (line 37) is executed at the end of the block that is declared (line 16) and returned (line 40).

If we didn’t want to use the macros (not advised at all - only shown for interest sake) then the implementation could remove the added complexity of setting up the DSL and end up with an implementation like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- (void (^)(id expected))_equal {
  __block id actual = self.actual;
  return [[^(id expected) {
    
    EXPBlockDefinedMatcher *matcher = [[EXPBlockDefinedMatcher alloc] init];
    
    matcher.matchBlock = ^BOOL{
      if((actual == expected) || [actual isEqual:expected]) {
        return YES;
      } else if([actual isKindOfClass:[NSNumber class]] && [expected isKindOfClass:[NSNumber class]]) {
        if(EXPIsNumberFloat((NSNumber *)actual) || EXPIsNumberFloat((NSNumber *)expected)) {
          return [(NSNumber *)actual floatValue] == [(NSNumber *)expected floatValue];
        }
      }
      return NO;
    };
    
    matcher.failureMessageForToBlock = ^NSString *{
      return [NSString stringWithFormat:@"expected: %@, got: %@", EXPDescribeObject(expected), EXPDescribeObject(actual)];
    };
    
    matcher.failureMessageForNotToBlock = ^NSString *{
      return [NSString stringWithFormat:@"expected: not %@, got: %@", EXPDescribeObject(expected), EXPDescribeObject(actual)];
    };
    
    [self applyMatcher:matcher to:&actual];
    
  } copy] autorelease];
  
}

This version seems like an awful lot of error prone boiler plate code that a developer would have to write for each matcher. Keep in mind that there are ~25 matchers included with Expecta and you can define your own.

Let’s list the required steps for this implementation:

  1. Creating an instance of EXPBlockDefinedMatcher (line 5)
  2. Configuring this instance’s properties with blocks for matchBlock (line 7), failureMessageForToBlock (line 18), and failureMessageForNotToBlock (line 22).
  3. Ensures that [self applyMatcher:matcher to:&actual]; is executed at the end of the block that is declared and returned (line 3).

In this implementation there are only 3 steps so this must surely be better?

Nope:

  • In the original list of 5 steps only step 4 was exposed to the developer and the remaining steps were hidden behind macros.
  • In this implementation the developer has to know about all 3 steps.
  • This means that the developer has 2 extra steps to remember to do and to make matters worse they are wrapping (before + after) steps.
  • In the first listing the developer is literally just stating the test requirements, whereas in this version the developer has to know about matchers and how they need to be configured in addition to the test requirements.

With all this knowledge we can now see that when we invoked equal(2) this gets expanded with #define equal(…) _equal(EXPObjectify((__VA_ARGS__))) to _equal(2), which is the name of the method that was added with a category on EXPExpect.

So hopefully now I’ve pulled back the curtain a little the line

expect(2).to.equal(2);

won’t seem as mysterious.


##Wrapping up

Well that was a heavy post with a lot to understand and I do apologise if I got any of it wrong - I’m no Expecta expert. Reading code is great fun especially when you get that Eureka moment and you learn something new. The joy of a project like Expecta is that it is all unit tested so you can hack around and change things to test your assumptions - hit test and wait for your theory to be validated with a sea of red or green unit test results.

Storyboard Constants

##Automate all the things

Storyboards can really speed up development but a problem I run into over and over again is working with identifiers that are set in the storyboard and referenced in code.

#Problem

Let’s take the example of making a segue:

You create a segue and then assign it an identifier in the storyboard… and that’s the problem. The identifier is defined in the storyboard, which leaves me with plenty of opportunities to mess up referencing the segue in code.

My normal strategy is to create a constants file that would have a constant with the value of each of these identifiers, which starts to look like the following (forgive the naming):

StoryboardConstants.h

extern NSString * const PSBMasterToDetail;
extern NSString * const PSBMasterToSettings;

This works for me and I’m happy, but it seems like a lot of manual graft and can become tiresome to maintain especially in a young project with lots of development spikes. It’s also still very possible to make typos and mess up these declarations or for them to become out of sync with the storyboard.

#Automation

I got to thinking about this problem and two things stood out

  1. I don’t like doing things manually and
  2. I don’t like that it is so easy to misspell a constant when swapping between storyboard and code (yes I am aware copy and paste exists).

So I started tinkering and I’ve come up with a rough tool that I’ve cunningly named sbconstants.

My automation idea is that you add a build script that will extract constants from your storyboards and then dump them into a file.

Grab it with

sudo gem install sbconstants

My first effort has a UI like this (command line app)

% sbconstants -h
Usage: DESTINATION_FILE [options]
    -p, --prefix=<prefix>            Only match identifiers with <prefix>
    -s, --source-dir=<source>        Directory containing storyboards
    -q, --queries=<queries>          YAML file containing queries
    -d, --dry-run                    Output to STDOUT
    -v, --verbose                    Verbose output

To get this working on a project the sbconstants gem needs to be installed to the system Ruby and then we need to call the executable from a build script. An example call would look like this

sbconstants MyApp/Constants/PASStoryboardConstants.h

NB The argument is the destination file to dump the constants into - this needs to be added manually

Every time this project is built it will parse the storyboard files and pull out any constants and then dump them into PASStoryboardConstants.(h|m). This of course means that PASStoryboardConstants.(h|m) should not be edited by hand as it will just be clobbered any time we build.

The output of running this tool will look something like this:

PASStoryboardConstants.h

// Auto generated file - any changes will be lost

#pragma mark - tableViewCell.reuseIdentifier
extern NSString * const PSBAwesomeCell;  

#pragma mark - segue.identifier
extern NSString * const PSBMasterToDetail;  
extern NSString * const PSBMasterToSettings;  

PASStoryboardConstants.m

// Auto generated file - any changes will be lost

#import "PASStoryboardConstants.h"

#pragma mark - tableViewCell.reuseIdentifier
NSString * const PSBAwesomeCell = @"PSBAwesomeCell";

#pragma mark - segue.identifier
NSString * const PSBMasterToDetail = @"PSBMasterToDetail";
NSString * const PSBMasterToSettings = @"PSBMasterToSettings";

The constants are grouped by where they were found in the storyboard xml e.g. segue.identifier. This can really help give you some context about where/what/when and why a constant exists.

##More options

Options are fun and there are a few to play with - most of these options are really only any good for debugging.

###--prefix -p, –prefix= Only match identifiers with

Using the prefix option you can specify that you only want to grab identifiers that start with a certain prefix, which is always nice.

###--source-dir -s, –source-dir= Directory containing storyboards

If you don’t want to run the tool from the root of your app for some reason you can specify the source directory to start searching for storyboard files. The search is recursive using a glob something like <source-dir>/**/*.storyboard

###--dry-run -d, –dry-run Output to STDOUT

If you just want to run the tool and not write the output to a file then this option will spit the result out to $stdout

###--verbose -v, –verbose Verbose output

Perhaps you want a little more context about where your identifiers are being grabbed from for debugging purposes. Never fear just use the --verbose switch and get output similar to:

sample output

#pragma mark - viewController.storyboardIdentifier
//
//    info: MainStoryboard[line:43](viewController.storyboardIdentifier)
// context: <viewController restorationIdentifier="asd" storyboardIdentifier="FirstViewController" id="EPD-sv-vrF" sceneMemberID="viewController">
//
NSString * const FirstViewController = @"FirstViewController";

###--queries -q, –queries= YAML file containing queries

Chances are I’ve missed some identifiers to search for in the storyboard. You don’t want to wait for the gem to be updated or have to fork it and fix it. Using this option you can provide a YAML file that contains a description of what identifers to search for. The current one looks something like this (NB this is a great starting point for creating your own yaml):

queries

---
segue: identifier
tableViewCell: reuseIdentifier
view: restorationIdentifier
? - navigationController
  - viewController
  - tableViewController
: - storyboardIdentifier
  - restorationIdentifier
  

This looks a little funky but it’s essentially groups of keys and values (both the key and the value can be an array). This actually gets expanded to looks for

+----------------------+-----------------------+
|         node         |      attribute        |
+ ---------------------+-----------------------+
| segue                | identifier            |
| tableViewCell        | reuseIdentifier       |
| view                 | restorationIdentifier |
| navigationController | storyboardIdentifier  |
| viewController       | storyboardIdentifier  |
| tableViewController  | storyboardIdentifier  |
| viewController       | restorationIdentifier |
| navigationController | restorationIdentifier |
| tableViewController  | restorationIdentifier |
+----------------------+-----------------------+

#Conclusion

I’m not sure if this tool will be of any use to anyone but for the projects I’ve been tinkering with it seems to work pretty well leaving me confident that my storyboard identifier’s will not go out of sync with how they are referenced in code.

If anyone does use this and they like it or they have any issues please report it to me so I can get it fixed up and improve my own workflow.

Blockception

Blocks are a lot of fun and they can make some really slick API’s. It’s also worth noting that blocks also require a fair amount of overhead to get used to how they work and how to use them. I would consider myself fairly competent with blocks but this confidence can lead to potentially “clever code”. “Clever code” is sometimes hard to maintain depending on how clever you was feeling at the time of writing it.

In this post I intend to cover one such bit of “clever code” and how it could be implemented differently to compare and contrast the results.

##Using delegates

I’ll start by looking at the implementation I didn’t actually do and then step by step arrive at the solution I initially wrote. From here I can compare and contrast and see which solution I should have done.

The sequence of events looks something like this

Delegate Implementation

So at this point we have a working solution and all is good.

The code to loop over the points looks something like this

View.m

for (int i = 0; i < self.dataSource.numberOfPoints; i++) {
  CGPoint point = [self.dataSource pointAtIndex:i];
  // convert point and build path
}

Something about asking for the count and then iterating over it seems a little awkward to me, I’d much rather the thing that held this information (the model) kept it’s data a little closer to it’s chest and iterated over itself passing out the points. There are two options here

  1. Implement NSFastEnumeration
  2. Add some kind of enumerator

I prefer the second option

##Block enumeration

The block enumeration ends up looking like this:

Model.m

- (void)enumeratePointsWithBlock:(void (^)(CGPoint point, NSUInteger idx, BOOL *stop))block;
{
  BOOL exitLoop = NO;
  
  for (int i = 0; i < self.locationCount; i++) {
    block(CGPointMake(self.locations[i], self.locations[i]), i, &exitLoop);
    if (exitLoop) {
      break;
    }
  }
}

This creates an issue - for this to work I would have to call this enumerator in the View. I could simply bypass the Controller and pass the View a reference to the Model but I don’t like the sound of this. The more pressing issue is that the Model works in a different coordinate space to the View and the Controller is currently handling this conversion.

To get this to work I’ll need to restructure to look like this

Enumeration Implementation

This diagram actually looks simpler. There’s a couple of things to now note

  • There are new required methods that need to be called and in a specific order beginDrawing and commitDrawing
  • The path building now occurs over a series of method calls to View

Straight away I can see a way to remove the requirement to call beginDrawing and commitDrawing at this level by using a block that wraps this up in a tasty sandwich.

##Sandwich block

The sandwich block puts the interesting code that changes as the sandwich filler and the boilerplate as the bread, which will look like this:

Model.m

- (void)drawWithBlock:(void (^)(void))block;
{
  [self beginDrawing];
  block();
  [self commitDrawing];
}

This hides a message in our sequence diagram and removes the requirement to remember to call beginDrawing and commitDrawing.

Sandwich Implementation

So actually getting the View to draw can now all be kicked off from the Controller and would look something like this:

Controller.m

- (void)drawGraph;
{
  [self.view drawWithBlock:^{
    [self.model enumeratePointsWithBlock:^(CGPoint point){
      [self.view buildWithPoint:[self convertPoint:point]];
    }];
  }];
}

Now at this point we can look at the public interfaces of the MVC trio and it’s looking quite smart

Model.m

- (void)enumeratePointsWithBlock:(void (^)(CGPoint point, NSUInteger idx, BOOL *stop))block;

Controller.m

- (void)drawGraph;

View.m

- (void)drawWithBlock:(void (^)(void))block;
- (void)buildWithPoint:(CGPoint)point;

Every object appears to be toeing the MVC line, although I see a method that probably doesn’t belong in the public API. The View now has the method -[View buildWithPoint:], which only makes sense in the context of drawing, it’s not clear by looking at the public interface what this method does or in what context to call it.

So here’s another opportunity to use a block, this final implementation brings us to the title of this post Blockception. We now end up with a block in a block which calls a block passed in by the first block.

This ends up looking like the following:

View.h

typedef void (^draw_point_b)(CGPoint drawPoint);

Controller.m

- (void)drawGraph;
{
  [self.view drawWithBlock:^(draw_point_b drawBlock) {
    [self.model enumeratePointsWithBlock:^(CGPoint point){
      drawBlock([self convertPoint:point]);
    }];
  }];
}

The drawBlock essentially takes the functionality of the old -[View buildWithPoint:] and passes it straight where it is actually needed.

##Differences

###Delegate Implementation

The delegate implementation requires a fair amount more code to write. A @protocol needs to be introduced to allow the view to have a dataSource. There is also the methods on the controller that conform to this protocol and end up proxying them straight onto the Model and then slightly changing the result.

Looking at the initial sequence diagram there seems to be more back and forth of messages to achieve the same result than where we end up.

The Model is required to expose how many elements it has and then allow an external object to iterate over that in a way which is out of it’s control.

###Block Implementation

The block implementation has 2 of my favorite ways to use blocks, which are for enumeration and wrapping code.

The public interfaces for all the objects expose very little about themselves, which is always nice.

There are considerably more awkward carets and curly braces, which can be confusing.

##Conclusion

Looking back at both solutions the delegate technique can be easier to fully grasp and follow along. The block implementation completely failed my “can I explain how this is working to a colleague in one attempt” rule, but I feel the delegate setup would only fair slightly better.

The reason I originally implemented this using blocks over delegates was purely because I had the block enumeration on the Model and this was the only way I could think to make it all fit.

I do like how the block implementation hides away any gory details about the structures of the objects but the very fact that I’ve had to write a blog post about this probably means it’s too clever. I think the answer to “which is better?” is we’ll have to wait and see how the block implementation stands up over time.