Objective C

Rosetta.h

// Copyright (c) 2007 Art & Logic, Inc. All Rights Reserved.

// $Id: Rosetta.h,v 1.2 2008/03/03 20:55:04 jschindler Exp $


// Above: [sf02], [sf03]



// a note on the stuff inside the square brackets:

// Each of the codes inside brackets is a reference to the rule(s) in the

// Style Guide that's being illustrated, as follows:

// [sf##] - StyleGuide/SourceFiles

// [cas##] - StyleGuide/ClassesAndStructures

// [nr##] - StyleGuide/NamingRules

// [cg##] - StyleGuide/Commenting

// [fmt##] - StyleGuide/Formatting


// Throughout: [fmt01]; all indentation done with space characters (0x20),

// three spaces per logical tab stop.


// [sf05]

// !!! #import preferred in objc over #include since it has implicit recursive include protection

#import "AlTypes.h"


// [nr25] the 'q' prefix indicates that we are controlling conditional

// compilation

#define qVerbose



// [sf07], only one class declared/defined in this source file.


// [cg02], comments useful to programmers who will use (but not necessarily

// maintain) this class are separated out into the header file, not in the

// implementation file.


/**

* An enum.

* More detailed enum description.

*/

// [nr08] new non-class types (enumerations, data structures, etc) are

// named with MixedCase and no special prefix

enum EnumName

{

// [nr23] identifiers specifying constants for the program are always

// prefixed with a lowercase 'k'.

kSomeConstant = 50,

kSomeOtherConstant = 100

};


/**

* @class ARosetta

* @brief Simple, but meaningless class to demonstrate Art+Logic programming

* style conventions as they are applied to the various programming languages

* we use. In several places, you're asked to imagine a block of useful code

* to avoid distracting you from the issues of formatting (etc) that are being

* demonstrated.

*

* As you've already seen above, the thing about to be shown in this file is

* called out in comments using the A+L-style markup '!!!'

*/

// [nr11], [nr18] class names prefixed with "A"

// !!! All classes in objc should subclass NSObject

@interface ARosetta : NSObject

{

// [cas01] !!! Access levels not valid for methods

// Private methods defined in implementation file (.m) using a category (optional)



// [cas02] member variables declared in the same order: public

// (avoid in most languages), protected, private.

// !!! private by default in objc

@public


@protected


@private

// [nr04], [nr19] Member variables are prefixed with a lowercase 'f', followed

// by an uppercase letter.

NSString* fFilename;

// [fmt28] -- when declaring pointer variables, attach the '*' to the

// typename, not the variable name.

NSFileHandle* fInputFile;


SInt32 fProcessResult;

}


//Properties do not need the 'f' prefix. There is no need to define a member variable

//unless you need one.

@property (nonatomic, strong) path;

//[nr04] You can also define member variables like this. Use the prefix 'f' when

//you override the default.

@property (nonatomic, strong) path=fPath;



/**

* Initialize the Rosetta object.

* @param fileName The file to use as our data source.

*/

-(id)InitWithFileName:(NSString*)fileName;


/**

* Destroy the Rosetta object, performing any needed cleanup.

*/

-(void)dealloc;


/**

* Member function does things.

* @return YES if successful, NO otherwise.

*/

/**

* [nr07] In objc, class methods (other than a class' constructor) begin with

* a lowercase letter, and additional words in the method name are capitalized.

*/

-(BOOL)memberFunctionWithMultipleWords;


// !!! Here's how we handle very long lines (i.e., longer than 79

// characters)

-(BOOL)longLineWrapping;


// !!! Loop formatting

-(void)loops;


// [nr03] parameters passed to functions are named using lowerCamelCase

// !!! Note the label for the second parameter, making the calling convention

// more descriptive in objc

-(BOOL)testWithFirstVal:(SInt32)firstVal andSecondVal:(SInt32)secondVal;


@end


Rosetta.m

// Copyright (c) 2008 Art & Logic, Inc. All Rights Reserved.

// $Id: Rosetta.m,v 1.3 2008/03/20 19:41:36 bporter Exp $


// Above: [sf02], [sf03]



// a note on the stuff inside the square brackets:

// Each of the codes inside brackets is a reference to the rule(s) in the

// Style Guide that's being illustrated, as follows:

// [sf##] - StyleGuide/SourceFiles

// [cas##] - StyleGuide/ClassesAndStructures

// [nr##] - StyleGuide/NamingRules

// [cg##] - StyleGuide/Commenting

// [fmt##] - StyleGuide/Formatting


// Throughout: [fmt01]; all indentation done with space characters (0x20),

// three spaces per logical tab stop.


#import "Rosetta.h"


/**

* Category for private methods.

*/

@interface ARosetta (Private)


/**

* Useful function to process something or other.

* @param val What val is.

*/

-(void)process:(SInt32)val;


// Demonstrating the formatting of a switch statement.

-(void)decide:(UInt8)midiEventType;


@end


@implementation ARosetta (Private)


-(void)process:(SInt32)val

{

// [cg05] -- use '!!!' as a marker to indicate a section of code that

// requires attention

// !!!... removing old hardcoded value

// fProcessResult = 131;

// ...!!!

SInt32 result = val;

while (--val)

{

result *= val;

}

fProcessResult = result;

}


-(void)decide:(UInt8)midiEventType

{

// [fmt11] -- switch/case formatting.

switch (midiEventType)

{

// comments precede the case

case kNoteOn:

[self NoteOn:now];

if (duration > 0)

{

[self noteOff:now + duration];

}

break;

case kNoteOff:

[self NoteOff:now];

break;

case kPolyAfter:

after = channelValue;

// [fmt35] include, but comment out the break when falling through intentionally.

// break;

case kChannelAfter:

[self AfterTouch:after];

break;

// [fmt36] no need to include a commented out break when falling through an empty case

case kPitchbend:

// blank line...

// [fmt12] -- switch statements should always have a default case.

default:

NSAssert(false, @"Unsupported event type!");

[self LogError:@"Unsupported event type!"];

break;

}

}


@end


@implementation ARosetta


-(id)initWithFileName:(NSString*)fileName

{

// !!! only proceed with initialization if our super init succeeds

if (nil != (self = [super init]))

{

fFileName = [fileName copy]; // !!! make our own local copy

fInputFile = [[NSFileHandle fileHandleForReadingAtPath:fileName] retain]; // !!! retain autorelease object

fProcessResult = 0;

}

// !!! make sure you return self!

return self;

}


-(void)dealloc

{

[fFileName release];

[fInputFile release];

// !!! must call super's dealloc

[super dealloc];

}


-(BOOL)memberFunctionWithMultipleWords

{

BOOL ok = true;

SInt32 i;

SInt32 j;

// [fmt08] -- formatting of a for() loop.

// !!! note that gcc by default doesn't allow the loop variable definition inside the for statement

for (i = 0; i < kSomeConstant; ++i)

{

for (j = 0; j < kSomeOtherConstant; ++j)

{

// [fmt02] -- preprocessor directives go in column zero.

#ifdef qVerbose

NSLog(@"testing: %d, %d", i, j);

#endif

// [nr07] -- Calls to member functions of the current object are

// made through an explicit this-> pointer.

ok = [self test:i :j];

if (!ok)

{

NSLog(@"Fatal error testing: %d, %d", i, j);

goto CleanUp;

}

}

}

return true;


// [fmt02] -- labels used as the target of a goto are placed in column zero.

CleanUp:

// cleanup code here...

return false;

}


-(BOOL)longLineWrapping

{

// [fmt03] -- source lines should be less than 80 characters long.

// [fmt04] -- break lines at the most logical point

// 1 2 3 4 5 6 7

//34567890123456789012345678901234567890123456789012345678901234567890123456789

retval = [self functionWithManyArguments:longArgumentName1

Arg2:longArgumentName2

Arg3:longArgumentName3

Arg4:longArgumentName4];

}


-(void)loops

{

// [fmt08] -- for() loop; note the pre-incremented form of the loop control

int i;

for (i = 0; i < kSomeConstant; ++i)

{

// loop code here...

}


// [fmt09]

while (someBoolean)

{

// useful code...

}


// [fmt09] -- while loop with an empty body makes the emptiness explicit

while ([self someFuncReturningBool])

{

// intentionally empty...

}


// [fmt10] -- do/while loop.

// [fmt18] -- exception to the bracing rule saying that braces should

// always be on a line by themselves

do

{

// loop code here..

} while (someBoolean);

}


-(BOOL)testWithFirstVal:(SInt32)firstVal andSecondVal:(SInt32)secondVal

{

bool retval = true;

// [fmt07] -- if/else formatting

if (firstVal < secondVal)

{

// [cg06] -- use '$$$' as a marker to indicate a request that the

// following block of code be reviewed before a change is considered

// complete

// $$$ before

// [self Process:firstVal];

// $$$ after

// Shouldn't this be processing the first value in this case?

[self Process:firstVal];

// $$$ end

}

else if (secondVal > kSomeConstant)

{

[self Process:secondVal];

}

else

{

// [fmt18] -- use curly braces even in cases where the language doesn't

// require it to prevent maintenance errors.

retval = false;

}


return retval;

}


@end