I plan on including this work in a portfolio. Will this code get me hired or laughed at?More specifically:How would you rate the general complexity of the code?How bad does the code smell?Is the VC too fat?Glaring best practices mistakes?Follow-up questions:Can you expand on what you said about magic numbers? (Totally missed the bool/BOOL usually I'm better than that. The names w/2 are just temp renames for SO)I have a lot of .h files because I tried to refactor somethings, like animation and URL methods, into helpers, presumably to increase readability. Did I go overboard?In theory, the way the program is setup, the MasterVC should never be deallocated. VC's are just pushed on top, not more than one layer at a time. Is it still necessary to unsubscribe from notifications?Lastly, on a scale of 1-10 what is your impression of the code overall? (from what you've seen and discounting the name and bool problem)   Details:iOS: 6 (updating to 7 currently) Xcode: 4.6Tested: iPhone 4 deviceARC EnabledMasterViewController.h#import <UIKit/UIKit.h>#import SRAPI.h#import SRChoiceBox.h#import SRPostTopic.h#import SRDetailViewController.h#import SRCollapsibleCell.h#import SRAnimationHelper.h#import SROpenTokVideoHandler.h#import SRObserveViewController.h@interface SRMasterViewController2 : UIViewController <UITableViewDelegate, UITableViewDataSource, SRChoiceBoxDelegate, SRPostTopicDelegate>@property (weak, nonatomic) IBOutlet UITableView *topicsTableView;@property (weak, nonatomic) IBOutlet UIView *postTopicContainer;@property (weak, nonatomic) IBOutlet UILabel *statusLabel;@property (strong, nonatomic) NSIndexPath *openCellIndex;@property (strong, nonatomic) RKPaginator *paginator;@property (strong, nonatomic) SROpenTokVideoHandler *openTokHandler;@endMasterViewController.m#import SRMasterViewController2.h#import UIScrollView+SVPullToRefresh.h#import UIScrollView+SVInfiniteScrolling.h#import SRUrlHelper.h#import SRNavBarHelper.h@interface SRMasterViewController2 ()@property NSInteger offset;@property NSInteger totalPages;@property NSMutableArray *topicsArray;@property bool isPaginatorLoading;@end@implementation SRMasterViewController2- (void)viewDidLoad {    [super viewDidLoad];    [self configureTableView];    [self configureNavBar];    [self configurePostTopicContainer];    [SRAPI sharedInstance];    [self paginate];    self.openTokHandler = [SROpenTokVideoHandler new];    [self configureNotifications];}- (void)configureNotifications {    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotifications:) name:kFetchNewTopicsAndReloadTableData object:nil];    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotifications:) name:kFetchRoomFromUrl object:nil];}- (void)receiveNotifications:(NSNotification *)notificaiton {    if ([notificaiton.name isEqualToString:kFetchRoomFromUrl]) {        NSURL *url = notificaiton.userInfo[@url];        [self fetchRoomWithUrl:url];    }    else if ([notificaiton.name isEqualToString:kFetchNewTopicsAndReloadTableData]) {        self.offset = 1;        [self.topicsTableView.infiniteScrollingView startAnimating];        [self paginate];    }}- (void)fetchRoomWithUrl:(NSURL *)url {    NSDictionary *dict = [SRUrlHelper parseQueryString:[url query]];    SRRoom *room = [[SRRoom alloc] init];    room.position  = (NSString *)[url pathComponents][3];    room.topicId = [url pathComponents][2];    room.sessionId = dict[@sessionID];    [self performSegueWithIdentifier:@showDetail2 sender:room];}- (void)configureNavBar {    //Button displays container for posting topics    UIBarButtonItem *rightPostTopicButton =    [SRNavBarHelper buttonForNavBarWithImage:[UIImage imageNamed:@logo]                            highlightedImage:nil                                    selector:@selector(showPostTopicContainer)                                      target:self];    self.navigationItem.rightBarButtonItem = rightPostTopicButton;    //suffle button - Joins random room    UIBarButtonItem *leftShuffleButton =    [SRNavBarHelper buttonForNavBarWithImage:[UIImage imageNamed:@shuffle.png]                            highlightedImage:[UIImage imageNamed:@shufflePressed.png]                                    selector:@selector(joinRandomRoom)                                      target:self];    self.navigationItem.leftBarButtonItem = leftShuffleButton;}- (void)joinRandomRoom {    NSMutableArray *activeTopics = [NSMutableArray new];    SRTopic *randomTopic = [SRTopic new];    SRRoom *randomRoom = [SRRoom new];    //find topics with people in them    for (SRTopic *topic in self.topicsArray) {        if ([topic.agreeDebaters integerValue] > 0 || [topic.disagreeDebaters integerValue] > 0) {            [activeTopics addObject:topic];        }    }    int numberOfActiveTopics = activeTopics.count;    if (numberOfActiveTopics > 0) {        //Put user into a random Active Room        int random = arc4random() % numberOfActiveTopics;        randomTopic = (SRTopic *)activeTopics[random];        if (randomTopic.agreeDebaters.intValue > randomTopic.disagreeDebaters.intValue) {            randomRoom.position  = @disagree;        }        else if (randomTopic.agreeDebaters.intValue < randomTopic.disagreeDebaters.intValue) {            randomRoom.position  = @agree;        }        else {            randomRoom.position = [self randomlyChooseAgreeDisagree];        }    }    else {        //No Active Rooms, put user in a random room        int random = arc4random() % self.topicsArray.count;        randomTopic = (SRTopic *)self.topicsArray[random];        randomRoom.position = [self randomlyChooseAgreeDisagree];    }    randomRoom.topicId = randomTopic.topicId;    [self performSegueWithIdentifier:@showDetail2 sender:randomRoom];}- (NSString *)randomlyChooseAgreeDisagree {    int r = arc4random() % 2;    return (r == 0) ? @agree : @disagree;}- (void)configureTableView {    //set offset for loading tabledata    self.offset = 1;    //add pull to refresh controls    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];    [refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];    [self.topicsTableView addSubview:refreshControl];    //add infinite scrolling    [self addInfiniteScrolling:self.topicsTableView];    //close all cells    self.openCellIndex = nil;    //Smooth scrolling    self.topicsTableView.layer.shouldRasterize = YES;    self.topicsTableView.layer.rasterizationScale = [[UIScreen mainScreen] scale];}- (void)configurePostTopicContainer {    //configure container for posting topics    SRPostTopic *postTopic = [[SRPostTopic alloc]initWithFrame:CGRectMake(0, 0, 320, 133)];    [self.postTopicContainer addSubview:postTopic];    postTopic.delegate = self;}- (void)addInfiniteScrolling:(UITableView *)tableView {    [tableView addInfiniteScrollingWithActionHandler: ^(void) {        self.offset += 1;        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{            [self paginate];            double delayInSeconds = 0.8;            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);            dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {                [self.topicsTableView.infiniteScrollingView stopAnimating];            });        });    }];    //configure infinite scrolling style    self.topicsTableView.infiniteScrollingView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;}- (void)refresh:(UIRefreshControl *)refreshControl {    self.offset = 1;    self.openCellIndex = nil;    //stop refresh after successful AJAX call for topics    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        [self paginate];        double delayInSeconds = 1;        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);        dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {            [refreshControl endRefreshing];        });    });}- (void)paginate {    // Create weak reference to self to use within the paginators completion block    __weak typeof(self) weakSelf = self;    // Setup paginator    if (!self.paginator) {        self.paginator.perPage = 20;        NSString *requestString = [NSString stringWithFormat:@?page=:currentPage&per_page=:perPage];        self.paginator = [[RKObjectManager sharedManager] paginatorWithPathPattern:requestString];        [self.paginator setCompletionBlockWithSuccess: ^(RKPaginator *paginator, NSArray *objects, NSUInteger page) {            NSMutableArray *topicsArrayTemp = [objects mutableCopy];            weakSelf.isPaginatorLoading = NO;            if (weakSelf.offset == 1) {                [weakSelf replaceRowsInTableView:topicsArrayTemp];            }            else {                [weakSelf insertRowsInTableView:topicsArrayTemp];            }            [weakSelf.topicsTableView.infiniteScrollingView stopAnimating];        } failure: ^(RKPaginator *paginator, NSError *error) {            weakSelf.isPaginatorLoading = NO;            [weakSelf.topicsTableView.infiniteScrollingView stopAnimating];            [weakSelf.self noResults];        }];    }    if (!weakSelf.isPaginatorLoading) {        weakSelf.isPaginatorLoading = YES;        [self.paginator loadPage:self.offset];    }}- (void)noResults {    double delayInSeconds = 0.6;    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);    dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {        [self performSegueWithIdentifier:@noResults sender:nil];    });}#pragma mark - Posting a new topic//open/close container for posting topics- (void)showPostTopicContainer {    [self.view endEditing:YES];    CGRect newTableViewFrame = self.topicsTableView.frame;    CGRect newPostTopicFrame = self.postTopicContainer.frame;    float duration, alpha;    if ([self isPostTopicContainerOpen]) {        newTableViewFrame.origin.y -= 133;        newPostTopicFrame.origin.y -= 133;        duration = .3;        alpha = 0;    }    else {        newTableViewFrame.origin.y += 133;        newPostTopicFrame.origin.y += 133;        duration = .4;        alpha = 1;    }    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations: ^{        self.postTopicContainer.alpha = alpha;        self.topicsTableView.frame = newTableViewFrame;        self.postTopicContainer.frame = newPostTopicFrame;    } completion:nil];}- (BOOL)isPostTopicContainerOpen {    return (self.postTopicContainer.frame.origin.y < 0) ? NO : YES;}//update fading status UILabel at the bottom of the screen- (void)statusUpdate:(NSString *)message {    self.statusLabel.text = message;    [self.statusLabel.layer addAnimation:[SRAnimationHelper fadeOfSRMasterViewStatusLabel] forKey:nil];}//Post a new Topic to the Server- (void)postTopicButtonPressed:(NSString *)contents {    //set up params    NSDictionary *newTopic = @{ @topic:contents };    //send new topic posting    [[RKObjectManager sharedManager] postObject:nil path:@topics/new parameters:newTopic success: ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {        if ([self isPostTopicContainerOpen]) {            //close post box if it's open            [self showPostTopicContainer];        }        [self statusUpdate:@Topic Posted!];    } failure: ^(RKObjectRequestOperation *operation, NSError *error) {        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@Oops                                                        message:@We weren't able to post your shout. Try again soon!                                                       delegate:nil                                              cancelButtonTitle:@Sure                                              otherButtonTitles:nil, nil];        [alert show];    }];}//Delegate for SRChoiceBox - user chooses Agree/Disagree/Observe- (void)positionWasChoosen:(NSString *)choice topicId:(NSNumber *)topicId {    SRRoom *room = [[SRRoom alloc] init];    room.position  = choice;    room.topicId = topicId;    if ([choice isEqualToString:@observe]) {        [self performSegueWithIdentifier:@showObserve sender:room];    }    else {        [self performSegueWithIdentifier:@showDetail2 sender:room];    }}- (void)segueToRoomWithTopicID:(NSNumber *)topicId andPosition:(NSString *)choice {    SRRoom *room = [[SRRoom alloc] init];    room.position  = choice;    room.topicId = topicId;    if ([choice isEqualToString:@observe]) {        [self performSegueWithIdentifier:@showObserve sender:room];    }    else {        [self performSegueWithIdentifier:@delete sender:nil];    }}- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {    //close Post Topic Container    if ([self isPostTopicContainerOpen]) {        [self showPostTopicContainer];    }    if ([[segue identifier] isEqualToString:@showDetail2] || [[segue identifier] isEqualToString:@showObserve]) {        if (self.openTokHandler) {            [self.openTokHandler safetlyCloseSession];        }        [[segue destinationViewController] setOpenTokHandler:self.openTokHandler];        [[segue destinationViewController] setRoom:sender];    }    sender = nil;}#pragma mark - UITABLEVIEW- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {    return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {    return [self.topicsArray count];}- (void)insertRowsInTableView:(NSMutableArray *)topics {    if (topics.count < 1) {        [self noNewResults];        return;    }    NSMutableArray *temp = [NSMutableArray new];    int lastRowNumber = [self.topicsTableView numberOfRowsInSection:0] - 1;    for (SRTopic *topic in topics) {        if (![self.topicsArray containsObject:topic]) {            [self.topicsArray addObject:topic];            NSIndexPath *ip = [NSIndexPath indexPathForRow:lastRowNumber inSection:0];            [temp addObject:ip];            ++lastRowNumber;        }    }    [self.topicsTableView beginUpdates];    [self.topicsTableView insertRowsAtIndexPaths:temp                                withRowAnimation:UITableViewRowAnimationTop];    [self.topicsTableView endUpdates];    if (temp.count == 0) {        [self noNewResults];    }}- (void)noNewResults {    int lastRowNumber = [self.topicsTableView numberOfRowsInSection:0] - 1;    [self statusUpdate:@No New Topics. Check Back Soon!];    [self.topicsTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:lastRowNumber - 6 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];    self.offset--;}- (void)replaceRowsInTableView:(NSMutableArray *)topics {    self.topicsArray = topics;    [UIView animateWithDuration:.3 delay:.5 options:UIViewAnimationOptionCurveEaseInOut animations: ^{        self.topicsTableView.layer.opacity = 0;    } completion: ^(BOOL finished) {        self.topicsTableView.layer.opacity = 1;        [[self.topicsTableView layer] addAnimation:[SRAnimationHelper tableViewReloadDataAnimation] forKey:@UITableViewReloadDataAnimationKey];        [self.topicsTableView reloadData];    }];}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    NSString *CellIdentifier2 = @SRCollapsibleCellClosed;    SRCollapsibleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];    if (cell == nil) {        cell = [[SRCollapsibleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];    }    SRTopic *topic = [self.topicsArray objectAtIndex:indexPath.row];    [cell updateWithTopic:topic];    if ([self isCellOpen:indexPath]) {        CGAffineTransform transformation = CGAffineTransformMakeRotation(M_PI / 2);        cell.arrow.transform = transformation;        if (![self hasChoiceBox:cell]) {            [self insertChoiceBox:cell atIndex:indexPath];        }    }    else {        CGAffineTransform transformation = CGAffineTransformMakeRotation(0);        cell.arrow.transform = transformation;    }    return cell;}- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    if ([self isCellOpen:indexPath]) {        [self closeCellAtIndexPath:indexPath];    }    else {        NSIndexPath *openCell = self.openCellIndex;        NSIndexPath *newOpenCell = indexPath;        [self closeCellAtIndexPath:openCell];        [self openCellAtIndexPath:newOpenCell];    }    [tableView beginUpdates];    [tableView endUpdates];    [tableView deselectRowAtIndexPath:indexPath animated:NO];}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {    if ([indexPath isEqual:self.openCellIndex]) {        return 217.0;    }    else {        return 63.0;    }}- (void)rotateCellArrowAtIndexPath:(NSIndexPath *)indexPath willOpen:(bool)willOpen animated:(bool)animated {    // Change Arrow orientation    SRCollapsibleCell *cell = (SRCollapsibleCell *)[self.topicsTableView cellForRowAtIndexPath:indexPath];    CGAffineTransform transformation;    if (willOpen) {        transformation = CGAffineTransformMakeRotation(M_PI / 2);    }    else {        transformation = CGAffineTransformMakeRotation(0);    }    if (animated) {        [UIView animateWithDuration:.2 delay:0 options:UIViewAnimationOptionCurveLinear animations: ^{            cell.arrow.transform = transformation;        }  completion:nil];    }    else {        cell.arrow.transform = transformation;    }}- (BOOL)isCellOpen:(NSIndexPath *)indexPath {    return [indexPath isEqual:self.openCellIndex];}- (void)closeCellAtIndexPath:(NSIndexPath *)indexPath {    [self rotateCellArrowAtIndexPath:indexPath willOpen:NO animated:YES];    [self removeSRChoiceBoxFromCellAtIndexPath:indexPath];    self.openCellIndex = nil;}- (void)openCellAtIndexPath:(NSIndexPath *)indexPath {    [self rotateCellArrowAtIndexPath:indexPath willOpen:YES animated:YES];    SRCollapsibleCell *cell = (SRCollapsibleCell *)[self.topicsTableView cellForRowAtIndexPath:indexPath];    [self insertChoiceBox:cell atIndex:indexPath];    self.openCellIndex = indexPath;}- (void)removeSRChoiceBoxFromCellAtIndexPath:(NSIndexPath *)indexPath {    SRCollapsibleCell *cell = (SRCollapsibleCell *)[self.topicsTableView cellForRowAtIndexPath:indexPath];    for (id subview in cell.SRCollapsibleCellContent.subviews) {        if ([subview isKindOfClass:[SRChoiceBox class]]) {            [subview removeFromSuperview];        }    }}- (void)insertChoiceBox:(SRCollapsibleCell *)cell atIndex:(NSIndexPath *)indexPath {    SRChoiceBox *newBox = [[SRChoiceBox alloc] initWithFrame:CGRectMake(0, 0, 310, 141)];    SRTopic *topic = [self.topicsArray objectAtIndex:indexPath.row];    [newBox updateWithSRTopic:topic];    newBox.delegate = self;    [cell.SRCollapsibleCellContent addSubview:newBox];}- (bool)hasChoiceBox:(SRCollapsibleCell *)cell {    for (UIView *subview in cell.SRCollapsibleCellContent.subviews) {        if ([subview isKindOfClass:[SRChoiceBox class]]) {            return true;        }    }    return false;}@end
MasterViewController
objective c;interview questions;ios
A few things I would ask if I saw this as an interviewer (from a very quick read, and obviously not having seen it run):why use a UIViewController and not a UITableViewController (refresh control property is free then)the rasterisation on table view shouldn't be needed for smooth scrolling, you have other problems if that is requiredthere are a few things which I wouldn't like to see and would ask about: magic numbers, names with a 2 at the end, inconsistencies (bool vs BOOL etc)why all the imports in the .h?why aren't the notification observers removed?Follow-up responses:makes sensewas just more about practice of importing .h files in a .h (meaning any class that needs to import your class knows about all those imported classes)It's just good practice I guess, but I didn't realise this was a permanent view controller Overall impressions are good (would depend a bit on the level of developer the job is for): the code is reasonably complex, uses 3rd party libraries, has some fairly advanced functions like dealing with layers / transforms. The real test though would be how well you can explain it during the interview, e.g. if you sound like its just a cut and paste job then the impression is lessened, but if you can explain your choices, pitfalls of the approach, anything you tried which you discard and why, and are able to talk about what you have learnt and where you would make improvements next time then you'd be looking pretty good I think. 