Kalekale koo, basizani babalalu nebaile kwa kulwalela likota.
A long time ago, three girls went
out to collect wood.
Munshita yakale, abakashana batatu baile mukuteba inkuni.
Neli lizazi lenelicisize hahulu konakuli sebaya kwa nuka kuyotapa. Neba bapala ni kufasaula ni kutapa mwa mezi.
It was a hot day so they went down
to the river to swim.
They played and splashed and
swam in the water.
Kwali ukwakaba sana, eyo baile mumumana mukowa. Bayangele nokowa mumenshi.
Hang’i hang’i, seba lemuha kuli seli likela. Sebaakufela kwahae.
Suddenly, they realised that it was
late.
They hurried back to the village.
Elyo baimwene ati bwaila. Babutukile ukubwelela kumushi.
Hase basutelezi kwandu, Nozibele aswala mwa mulala wahae. Nalibezi sifaha sahae sa mwa mulala! “Nakupa kukuta nina!” akupa balikani bahae. Kono balikani bahae babulela kuli seli busihu.
When they were nearly home,
Nozibele put her hand to her neck.
She had forgotten her necklace!
“Please come back with me!” she
begged her friends.
But her friends said it was too late.
Konakuli Nozibele akuta kwa nuka anosi. Ayofumana sifaha sa hae niku akufela kwa ndu. Kono alateha mwa lififi.
So Nozibele went back to the river
alone.
She found her necklace and hurried
home.
But she got lost in the dark.
Nozibele epakubwekelamo kumumana eka. Asendel akakufwala mumukoshi nokubweluluka bwangu bwangu ku mushi. Nomba aliluba munfifi.
Kwahule abona liseli lene lizwelela mwa situngu. Saakufela kwateni ni kukokota fa sikwalo.
In the distance she saw light
coming from a hut.
She hurried towards it and knocked
at the door.
Akatalamukila, amona ulubuto mukasaka. Eko aya bwangubwangu mukukonkosha pacibi.
Kakukomokisa, Nja yakwaulula sikwalo ni kubulela, “Kisikamani seubata?” “Nilatehile mi nibata malobalo,” Nozibele abulela. “Kena, hakusicwalo ni kakuluma!” Nja yabulela. Konakuli Nozibele akena mwahali.
To her surprise, a dog opened the
door and said, “What do you want?”
“I’m lost and I need a place to
sleep,” said Nozibele.
“Come in, or I’ll bite you!” said the
dog.
So Nozibele went in.
Cwale Nja seibulela, “Niapehele!” “Kono hanisika apehela kale nja,” aalaba. “Apeha, hakusicwalo ni kakuluma!”Nja yabulela. Konakuli Nozibele saapeha lico zemu za Nja.
Then the dog said, “Cook for me!”
“But I’ve never cooked for a dog
before,” she answered.
“Cook, or I’ll bite you!” said the dog.
So Nozibele cooked some food for
the dog.
Then the dog said, “Make the bed
for me!”
Nozibele answered, “I’ve never
made a bed for a dog.”
“Make the bed, or I’ll bite you!” the
dog said.
So Nozibele made the bed.
Zazi ni zazi naapehenga, kufiyela ni kutapiseza Nja. Cwale lizazi lelimu Nja yabulela, “Nozibele, kacenu niswanela kupotela balikani baka. Ufiyele ndu, uapehe lico ni kutapisa lika zaka nisikakuta kale.”
Every day she had to cook and
sweep and wash for the dog.
Then one day the dog said,
“Nozibele, today I have to visit
some friends. Sweep the house,
cook the food and wash my things
before I come back.”
Onafo Nja hase ile, Nozibele azusa milili yemilalu kwa toho yahae. Abeya mulili ulimumu mwatasi a mumbeta, ulimumu kwa mulaho wa sikwalo ni ulimumu mwa mulaka. Nikumatela kwandu ka bubebe mwana konela.

She put one hair under the bed, one
behind the door, and one in the
kraal.
Then she ran home as fast as she
could.
Nja haseikutile, yabata Nozibele. “Nozibele, ukai?” ya huwa. “Kinayo mwa tasi a mumbeta,” mulili wapili wabulela. “Kinayo kwa mulaho wa sikwalo,” mulili wa bubeli wabulela. “Kina yo mwa mulaka,” mulili wa bulalu wabulela.
When the dog came back, he looked
for Nozibele.
“Nozibele, where are you?” he
shouted.
“I’m here, under the bed,” said the
first hair.
“I’m here, behind the door,” said the
second hair.
“I’m here, in the kraal,” said the
third hair.
Nja seilemuha kuli Nozibele na ipumile. Kiha seimata kumatela kwa hae. Kono bahulwani ba Nozibele nebailibelezi ni litupa zetuna. Nja seifetuha nikubaleha mi haisika bonwa hape kuzwelela foo.
Then the dog knew that Nozibele
had tricked him.
So he ran and ran all the way to the
village.
But Nozibele’s brothers were
waiting there with big sticks.
The dog turned and ran away and
has never been seen since.


-
Introduction These are my coding guidelines as they currently stand. The source Scrivener document is available at https://github.com/richardbuckle/CodingGuidelines.
Points to note:
1. They are coding guidelines, not layout guidelines. If you are still obsessing about where braces should be placed, spaces vs tabs, etc, then I humbly submit that it's time to let go of all that. Professional coders can quickly adapt to any sane layout style if it's used consistently.
2. These are guidelines, not tram-lines....
-
Contents Contents
Compiler and build settings
Zero warnings and static analyser issues always <$p>
Use the standard TODO: comment <$p>
Logging and assertions
DLog not NSLog <$p>
Minimise use of logging <$p>
No meaningful code in NSAssert <$p>
Careful with NSAssert in blocks <$p>
Code architecture and design
Don't repeat yourself <$p>
Learn the "SOLID" principles <$p>
Be judicious about singletons <$p>
Minimise header dependencies <$p>
General best practices
Use string resources <$p>
No magic numbers <$p>...
-
Compiler and build settings
-
Zero warnings and static analyser issues always Zero warnings and static analyser issues always
Guideline:
Code submitted for review or integration must always compile cleanly with zero warnings and zero static analyser issues. Warnings must be investigated and resolved properly, not merely suppressed.
Rationale:
A zero-tolerance policy for compiler warnings is the only way to ensure that potentially serious warnings receive the attention that they need.
Sometimes a warning will flag a more insidious problem than the warning's message may ...
-
Use the standard TODO: comment Use the standard TODO: comment
Guideline:
Use the standard TODO: comment, not variations such as FIXME, todo , XXX etc, and explain clearly what needs to be done.
Bad:
foo(); // FIXME clean this up
Preferred:
foo(); // TODO: a clear explanation follows here
Rationale:
The TODO: comment is recognized by Xcode and displayed prominently in the jump-bar’s dropdown menu.
Permitted Exceptions:
None.
-
Logging and assertions
-
DLog not NSLog DLog not NSLog
Guideline:
We should nearly always prefer the DLog() macro from Marcus Zarra, Lumberjack, or the ECLogging module to NSLog(), so that we do not log unnecessarily in release builds.
Bad:
NSLog(@“someDict is @”, someDict);
Preferred:
DLog(@“someDict is @”, someDict);
Rationale:
Logging in release builds is very rarely of any value since we have very little access to logs on customers’ devices. Additionally, logging incurs a significant speed hit in instantiating an NSCalendar ...
-
Minimise use of logging Minimise use of logging
Guideline:
Don’t spam the log. Don't log success (what did you expect: a medal or something?). If your logging is to diagnose a particular ticket, delete it when you’re done (and, ideally, when you have written a unit test for the ticket).
Rationale:
Spamming the log console with unnecessary logging is rude to your colleagues because it makes it harder for them to see their own log messages when they are diagnosing something.
Permitted Exceptions:
If you have some logg...
-
No meaningful code in NSAssert No meaningful code in NSAssert
Guideline:
Do not put code that has side-effects in NSAssert and family, as it will be compiled away in release builds.
Bad:
NSAssert([self someMethod], @“someMethod failed”);
Good:
BOOL success = [self someMethod];
NSAssert(success, @“someMethod failed”);
Rationale:
Even if [self someMethod] looks benign today, the bad code introduces a subtle divergence in behaviour between debug and release builds that can bite us later should [self someMethod] be revised...
-
Careful with NSAssert in blocks Careful with NSAssert in blocks
Guideline:
Be aware that NSAssert references self. If used in a block that is retained by self, a retain cycle and thus a memory leak will occur.
Bad:
self.completionBlock = ^(BOOL success) {
NSAssert(success, @“failed”);
};
Good:
self.completionBlock = ^(BOOL success) {
if(!success) {
// DLog(@“failed”);
// Now handle it properly
}
};
Rationale:
A fuller description and an alternative macro that doesn’t reference self can be found here. Howeve...
-
Code architecture and design
-
Don't repeat yourself Don’t repeat yourself
Guideline:
Don’t copy-and paste code. Instead refactor that code. Particularly, don’t copy and paste and then change just a few things here and there. Instead, parameterise and refactor.
Rationale:
See the wikipedia article.
Repeated code is IMHO the most pernicious kind of technical debt. It is a massive maintenance risk because maintenance programmers will not be aware that if they find a bug, it will need to be fixed in multiple unrelated places of which they probably ...
-
Learn the "SOLID" principles Learn the "SOLID" principles
Guideline:
Learn and apply the “SOLID” design principles.
That is all.
-
Be judicious about singletons Be judicious about singletons
Guideline:
Think very carefully before using the singleton design pattern. Prefer dependency injection.
Bad:
- (void)someMethod {
FooManager *fooManager = [FooManager sharedInstance];
// do something with fooManager ...
Good:
- (void)someMethodWithFooManager:(FooManager *)fooManager {
// do something with fooManager ...
Rationale:
The singleton design pattern is often more of an anti-pattern. Singletons are just globals in disguise. They introduce...
-
Minimise header dependencies Minimise header dependencies
Guideline:
Strive to minimise header dependencies. Use forward declarations where possible.
Bad:
#import "Foo.h";
@interface Qux : NSObject {
Foo *foo;
// …
Good:
@class Foo;
@interface Qux : NSObject {
Foo *foo;
// …
Rationale:
Unnecessary header dependencies not only increase compile time unnecessarily, they increase code coupling because you are forcing these unnecessary dependencies on all users of your class.
As a rule, you only need to import h...
-
General best practices
-
Use string resources Use string resources
Guideline:
All strings visible in the UI should be in string resources, not string literals in code. Use informal structured naming for the key, not the default English text.
Bad:
label.text = @"Congratulations!";
Still not ideal:
label.text = NSLocalizedString(@"Congratulations!", nil);
Best:
label.text =<EMAIL_ADDRESS>nil);
Rationale:
It is a horrible job to have to go through the entire code base looking for string literals that...
-
No magic numbers No magic numbers
Guideline:
Use named constants instead of magic numbers.
Bad:
myView.size.width = 1024 - 42 - (4 + 4);
Better:
CGSize containerSize = containerView.frame.size;
myView.size.width = containerSize.width
- kReservedWidth - (kLeftPadding + kRightPadding);
Best:
Use AutoLayout.
Rationale:
One of the ultimate maintenance programming headaches. Six months later, no-one will have the faintest idea what the magic numbers mean.
Permitted Exceptions:
Dividing by 2 to get...
-
Always get the screen size at runtime Always get the screen size at runtime
Guideline:
Always get the screen size at runtime. Never hardwire it.
Bad:
myView.size.width = 1024 - 42 - (4 + 4);
Dubious:
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
// who said we're on the main screen?
myView.size.width = screenSize.width - kReservedWidth - (kLeftPadding + kRightPadding);
Best:
Use AutoLayout.
Rationale:
Hard-coding a fixed screen size hurts portability between iPhone and iPad, and doesn't cater for new hardware a...
-
Never compare against YES etc Never compare against YES etc
Guideline:
Never compare boolean expressions against YES, true, 1, etc.
Bad:
if(foo == YES) {
// ...
}
Good:
if(foo != NO) {
// ...
}
Best:
if(foo) {
// ...
}
Rationale:
All non-zero values represent truth. Comparison against YES, true, etc will give incorrect results when the value being compared is any other non-zero value.
Permitted Exceptions:
None. Such code is flat wrong.
-
Minimise preprocessor usage Minimise preprocessor usage
Guideline:
Minimise preprocessor usage. Prefer const and inline to #define.
Bad:
In the header:
#define kLookupKey @"blah"
Good:
In the header:
extern NSString *const kLookupKey;
In the implementation:
NSString *const kLookupKey = @"blah";
Rationale:
The C preprocessor is arguably the purest manifestation of programming evil imaginable. It smashes through all scoping rules and encapsulation defences. Worst of all, there is little or no defence against a pre...
-
No Hungarian naming No Hungarian naming
Guideline:
Do not use hungarian naming to encode the type of a variable or whether it is an objective-C property or instance variable in its name.
Rationale:
Quite apart from the unnecessary cognitive burden it adds to reading code, and the bad fit with a dynamically-typed language, to quote "How to Write Unmaintanable Code":
Hungarian Notation is the tactical nuclear weapon of source code obfuscation techniques... Due to the sheer volume of source code contaminated by this...
-
No uninitialised locals, ever No uninitialised locals, ever
Guideline:
Local variables should always be initialised to a safe value at the point of declaration, and should not be declared until they are needed.
Bad:
CGRect rect;
switch(something) {
// some code that doesn't cover all values
}
Good:
CGRect rect = CGRectNull;
switch(something) {
// some code that doesn't cover all values
}
Rationale:
If not initialised, local variables get garbage values. This is never good.
Permitted Exceptions:
Under ARC, Coco...
-
Objective-C best practices
-
Dot notation is for genuine properties only Dot notation is for genuine properties only
Guideline:
Dot notation is only for getting and setting properties. Do not abuse it to call methods that are not property getters or setters.
Bad:
UIView *view = …;
view.sizeToFit; // WRONG, not a property
Good:
UIView *view = …;
[view sizeToFit];
CGRect frame = view.frame;
Rationale:
Abusing dot notation to call non-property methods is not supported and may well break in future. Regardless, it is highly misleading to maintenance programmers.
...
-
Avoid mutable container properties Avoid mutable container properties
Guideline:
Avoid mutable container properties.
Bad:
@interface Foo {
@property (readwrite, retain) NSMutableArray *someArray;
Good:
@interface Foo {
@property (readwrite, retain) NSArray *someArray;
Rationale:
Mutable container properties allow the contents of the property to be modified without the owning object's knowledge. This severely violates encapsulation, and breaks fundamental Cocoa technologies such as key-value-observing.
Because Cocoa conta...
-
Beware of retain cycles with blocks and self Beware of retain cycles with blocks and self
Guideline:
If self retains a block that references self, a retain cycle and a memory leak will occur.
Bad:
self.completionBlock = ^() {
[self someMethod];
};
Good:
Without ARC…
__block id weakSelf = self;
self.completionBlock = ^() {
[weakSelf someMethod];
};
With ARC…
__weak id weakSelf = self;
self.completionBlock = ^() {
[weakSelf someMethod];
};
Rationale:
Obviously the retain cycle is bad news and needs to be avoided.
Permitt...
-
Version control
-
Follow the standard for Git commit messages Follow the standard for Git commit messages
Guideline:
To fit well with the various tools, Git commit messages should have an initial, brief, summary line followed by any necessary detail on subsequent lines.
Bad:
[a ton of text all on one line]
Good:
Fix ticket #345
The issue turned out to be […].
The fix was to […].
Unit test […] has been added to guard against regressions.
Rationale:
All the various tools for viewing Git logs work best if the initial summary line is relatively short, pr...
-
Cite ticket numbers in commit messages Cite ticket numbers in commit messages
Guideline:
If your commit is related to any ticket numbers (for bugs or work units), cite those numbers in your Git commit message.
Rationale:
This permits two-way linking between commits (aka changesets) and tickets. It is particularly useful for maintenance programmers to use git blame to find the changeset for a given line of code and thus tell what ticket motivated it.
Permitted Exceptions:
Sometimes, especially during bring-up, commits will be gener...
-
Use submodules for 3rd-party code Use submodules for 3rd-party code
Guideline:
3rd-party code should be maintained in a Git repo of its own and a defined tag should be pulled into the working project as a Git submodule.
Rationale:
This allows us to track revisions of the 3rd-party code, integrate any fixes that we've made in any branches of our own, all without disturbing production code. Once integration testing is complete, we can then point the production code to a new tag on the submodule.
Permitted Exceptions:
Legacy pro...
 Before you commit, delete any commented-out code.
Rationale:
We have version control to get back the old code if we need it. Commented-out code wastes everyone's time by forcing every maintenance programmer who encounters it to try to figure out why it was commented out and whether it needs to be kept.
Permitted Exceptions:
If you have code that is needed periodically e.g. for testing or benchmarking, dis...
-
Don't sign your comments Don't sign your comments
Guideline:
The old school convention of signing your comments with your initials and a timestamp are redundant in the age of version control. Write good version control comments instead.
Rationale:
Don't add redundant cognitive burden to the codebase. If I need to see who wrote it, when and why, I'll look in version control.
Permitted Exceptions:
None.
-
Document History
|
|
|


Forever is a demonstration application for personal clouds. At present, Forever uses SquareTag as its personal cloud. We hope to support other personal cloud providers in the near future.
Forever stores no personal data whatsoever. Forever relies entirely on the personal cloud for storing data, knowing friend relationships, and sending notifications. Any data changes made in Forever are reflected in the linked personal cloud and no where else. As a result, Forever has no privacy policy of its own. The privacy policy of the personal cloud provider is what is relevant.
For more information about Forever, see Phil Windley's white paper:
| Name |
|---|
| Ed Orcutt |
| Steve Fulling |
| Phil Windley |
View Logout
Page Not Found