HiveBrain v1.2.0
Get Started
← Back to all entries
patternModerate

Spawning a Dog class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
spawningclassdog

Problem

When the app is run on an iPhone or simulator, tapping the screen spawns a dog class and displays an image of the dog.

I'd like comments, issues, whatever. Is this a decent first Objective-C project, and can others learn from it?

The code is meant to demonstrate Objective-C, Cocoa and UIKit.

Primary files in the project:

Protocols

GKLiving.h

//
//  GKLiving.h
//  SampleApp
//

// Cocoa foundation classes
#import 

#pragma mark - Defines

#pragma mark - The Living protocol of the GK namespace

@protocol GKLiving 

#pragma mark - Mandatory methods

#pragma mark - Optional methods

@optional

@end


GKAnimalia.h

//
//  GKAnimalia.h
//  SampleApp
//

// Cocoa foundation classes
#import 

#import "GKLiving.h"

#pragma mark - Defines

#pragma mark - The Animalia protocol of the GK namespace

@protocol GKAnimalia 

#pragma mark - Mandatory methods

  + (NSString *)stringRepresentationOfBreed;

#pragma mark - Optional methods

@optional

@end


GKCanidae.h

//
//  GKCanidae.h
//  SampleApp
//

// Cocoa foundation classes
#import 

#pragma mark - Defines

#define GKCANIDAE_UNKNOWN_BREED @"Mutt"

#pragma mark - The Canidae protocol of the GK namespace

@protocol GKCanidae 

#pragma mark - Mandatory methods

  // Note that the "+" makes this a class-level method (it is
  // not an instance method).
  + (NSString *)says;

#pragma mark - Optional methods

@optional

@end


Dog Classes

GKDog.h

```
//
// GKDog.h
// SampleApp
//

// Cocoa foundation classes
#import

// Protocols
#import "GKAnimalia.h"
#import "GKCanidae.h"

#pragma mark - Defines

#define GKDOG_PRIVATE_THOUGHTS @"I love you"
#define GKDOG_SOUND @"Arf"
#define GKDOG_PLACEHOLDER_PATH \
[[NSBundle mainBundle] pathForResource:@"how-to-draw-a-dog-4" ofType:@"jpg"]

#pragma mark - The Dog class of the GK namespace

// 1. No namespaces in Objective-C, so class prefixes are used instead.
// The "NS" prefix (for NextStep, I assume) is pretty common.
// 2. This class conforms to the GKCanid

Solution

Because this question is so, so large, I won't get into all the specifics of everything I see. I will point out some things, and provide some examples from one file or another, and as you work through my answer, you should work through your project to find all the other instances of an example I point out.

I will start with a simple answer to the topic question:
Is this a decent first Objective-C project, and can others learn from it?

Simply, yes. I haven't built and compiled and tried running this, but I assume you have. Certainly anyone whose Objective-C knowledge is below that of this project would be able to learn from it. And it's fairly well organized, clean, etc, so I'll pass it as decent as well.

But in the first few paragraphs, you talk about wanting for a project to serve as an example of Objective-C "standard practice". A perfectly fine want--but let's be clear, this project isn't that.

Also, while I did say that someone could learn from this project, I think the audience of people who would take the time to learn from this is fairly narrow. At least in my personal experience as a programmer, I learn best when adding small chunks of knowledge at a time. To me, learning programming is like having a rubber band ball. It's really hard to get that ball started. But once you do, all you have to do to keep it going is snap one more rubber band on here and there.

Your project is, in my opinion, a bit too complex for Objective-C and iOS beginners and covers far too much ground. And the project contains some problems that if a more advanced Objective-C user "learned" as the way to do it, he wouldn't have benefited all that much.

So, now that that's out of the way, I'll start at the top, and work my way down.

It is likely that this answer my be broken into multiple answers or will receive future edits. Basically, treat this as an answer in progress, as there's quite a few things here I want to address, and I won't be able to address it all in one sitting--you didn't write this whole project in one sitting, did you?

First of all, some of the problems that are consistent throughout the entirety of the project:

EDIT: As a note here, I'm pointing to sections of your code you've marked off with a #pragma mark. I wanted to come back and edit in some clarity. The #pragma mark themselves are for the most part okay. These are basically just comments with some special features, and using #pragma marks to mark off sections is great. I'm mostly discussing the content in each of these sections.

#pragma mark - Namespace ...

// 1. No namespaces in Objective-C, so class prefixes are used instead.
// The "NS" prefix (for NextStep, I assume) is pretty common.


Correct and correct. "NS" does stand for NextStep. In iOS development, most of the Foundation classes you'll use are prefixed with NS or UI. You'll run into some other common ones too like CG, AF, etc.

But more importantly, you're correct about the fact that there are no namespaces in Objective-C. As such, a project hoping to serve as the "standard practice" for Objective-C shouldn't have a #pragma mark - Namespace in every single header file in its project. True Objective-C projects should have this no where. Best case scenario, you might see it in an Objective-C++ project.

It is perfectly fine for a programmer coming from a non-Objective-C background to do something like this if it helps the organization of the project because he's used to thinking of it in some other way, but it's definitely not "standard practice".

#pragma mark - Defines

You've included this line in most of the files. The fact of the matter is, you shouldn't be using #define so often that it's a regularly occurring section in your code.

Certainly, you shouldn't be using #define simply for constant values. That's what the const keyword is for. And if you need to declare a constant value in a .h file so it can be seen by multiple files, well, that's what the extern keyword is for.

So for example this:

#define GKDOGSPAWNER_IMAGE_MIN_X 0.0f


Should be replaced with this:

extern CGFloat const DKDOGSPAWNER_IMAGE_MIN_X;


in the .h, and then define it in the .m of the same file:

CGFloat const DKDOGSPAWNER_IMAGE_MIN_X = 0.0f;


Applying this thinking to all of your defines eliminates all but 3 of the #defines.

The last three could also potentially be eliminated via functions. For example:

#define GKDOGSPAWNER_IMAGE_MAX_X ([UIScreen mainScreen].bounds.size.width - GKDOGSPAWNER_IMAGE_WIDTH)


could be replaced with:

CGFloat GKDOGSPAWNER_IMAGE_MAX_X();


in the .h, then define the function in the .m:

CGFloat GKDOGSPAWNER_IMAGE_MAX_X() {
    return ([UIScreen mainScreen].bounds.size.width - GKDOGSPAWNER_IMAGE_WIDTH);
}


In this case though, the #define doesn't bother me as much.

These points on #define aren't really even Objective-C specific. They can apply across all of t

Code Snippets

// 1. No namespaces in Objective-C, so class prefixes are used instead.
// The "NS" prefix (for NextStep, I assume) is pretty common.
#define GKDOGSPAWNER_IMAGE_MIN_X 0.0f
extern CGFloat const DKDOGSPAWNER_IMAGE_MIN_X;
CGFloat const DKDOGSPAWNER_IMAGE_MIN_X = 0.0f;
#define GKDOGSPAWNER_IMAGE_MAX_X ([UIScreen mainScreen].bounds.size.width - GKDOGSPAWNER_IMAGE_WIDTH)

Context

StackExchange Code Review Q#46357, answer score: 13

Revisions (0)

No revisions yet.