Pergunta

Sendo novo no programador Objective-C (mas um programador C/++ de longo prazo), estou procurando conselhos/recomendações sobre convenções de nomenclatura para variáveis.

Minha preferência pessoal seria utilizar um prefixo para variáveis ​​de instância, tanto para maior clareza nas funções quanto para evitar o sombreamento dos parâmetros da função.No entanto, sou fã de propriedades que excluem prefixos (a menos que você também prefixe os nomes de suas propriedades, o que não funciona muito bem e parece idiota).Da mesma forma, eu poderia usar a convenção "self.variable", mas somente se eu transformar EVERYTHING em uma propriedade.

Então, dado o código abaixo, qual é o seu estilo de nomenclatura preferido para variáveis ​​de instância/função?E se você não se incomoda, como você lida com o sombreamento dos parâmetros de função?

@interface GridItem : NSObject
{
    CGRect _rect;
    ...  
}
@end

-(void) initFromRect:(CGRect)rect
{
    _rect = rect;
    ...
}

Saúde!

Foi útil?

Solução

A maioria dos projetos de cacau usa o underbar como um recurso não-IBOutlet prefixo da variável de instância e não use prefixo para IBOutlet variáveis ​​de instância.

A razão pela qual não uso underbars para IBOutlet variáveis ​​​​de instância é que quando um arquivo nib é carregado, se você tiver um método setter para uma tomada conectada, esse setter será chamado. No entanto esse mecanismo faz não use codificação de valor-chave, portanto, um IBOutlet cujo nome é prefixado com uma barra inferior (por exemplo. _myField) vai não ser definido, a menos que o setter tenha o mesmo nome da tomada (por exemplo. set_myField:), o que é fora do padrão e grosseiro.

Além disso, esteja ciente de que o uso de propriedades como self.myProp é não o mesmo que acessar variáveis ​​de instância.Você é enviando uma mensagem quando você usa uma propriedade, como se você usasse notação de colchetes como [self myProp].Todas as propriedades fornecem uma sintaxe concisa para especificar o getter e o setter em uma única linha e permitem sintetizar sua implementação;na verdade, eles não causam curto-circuito no mecanismo de envio de mensagens.Se você quiser acessar uma variável de instância diretamente, mas prefixá-la com self você precisa tratar self como um ponteiro, como self->myProp que realmente é um acesso de campo no estilo C.

Finalmente, nunca use a notação húngara ao escrever código Cocoa e evite outros prefixos como "f" e "m_" - isso marcará o código como tendo sido escrito por alguém que não "entendeu" e fará com que ele ser visto com suspeita por outros desenvolvedores do Cocoa.

Em geral, siga os conselhos do Diretrizes de codificação para cacau documento no Conexão de desenvolvedor Apple, e outros desenvolvedores serão capazes de entender e entender seu código, e seu código funcionará bem com todos os recursos do Cocoa que usam introspecção em tempo de execução.

Esta é a aparência de uma classe de controlador de janela, usando minhas convenções:

// EmployeeWindowController.h
#import <AppKit/NSWindowController.h>

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    IBOutlet NSTextField *nameField;
    IBOutlet NSTextField *titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;

@end

// EmployeeWindowController.m
#import "EmployeeWindowController.h"

@implementation EmployeeWindowController

@synthesize employee = _employee;

- (id)initWithEmployee:(Employee *)employee {
    if (self = [super initWithWindowNibName:@"Employee"]) {
        _employee = [employee retain];
    }
    return self;
}

- (void)dealloc {
    [_employee release];

    [super dealloc];
}

- (void)windowDidLoad {
    // populates the window's controls, not necessary if using bindings
    [nameField setStringValue:self.employee.name];
    [titleField setStringValue:self.employee.title];
}

@end

Você verá que estou usando a variável de instância que faz referência a um Employee diretamente no meu -init e -dealloc método, enquanto estou usando a propriedade em outros métodos.Geralmente, esse é um bom padrão com propriedades:Toque apenas na variável de instância subjacente para uma propriedade em inicializadores, em -dealloc, e no getter e setter da propriedade.

Outras dicas

Sigo o conselho de Chris Hanson em relação ao prefixo ivar de sublinhado, embora admita que também uso sublinhado para IBOutlets.No entanto, recentemente comecei a mover meu IBOutlet declarações ao @property linha, conforme Sugestão do @mmalc.A vantagem é que todos os meus ivars agora têm um sublinhado e os setters KVC padrão são chamados (ou seja, setNameField:).Além disso, os nomes dos pontos de venda não possuem sublinhados no Interface Builder.

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    NSTextField *_nameField;
    NSTextField *_titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;
@property(nonatomic, retain) IBOutlet NSTextField *nameField;
@property(nonatomic, retain) IBOutlet NSTextField *titleField;

@end

Você pode usar o prefixo underbar em seus ivars e ainda usar o nome não underbar para suas propriedades.Para acessadores sintetizados, basta fazer isto:

@synthesize foo = _foo;

Isso diz ao compilador para sintetizar a propriedade foo usando the_foo ivar.

Se você escrever seus próprios acessadores, basta usar o ivar underbar em sua implementação e manter o nome do método não underbar.

Pessoalmente, sigo as convenções de nomenclatura do Cocoa, usando camel-casing para funções e variáveis, e camel-casing em maiúscula para nomes de objetos (sem o NS inicial, é claro).

Acho que o prefixo de tipo torna o código mais opaco para quem não o escreveu (já que todos invariavelmente usam prefixos diferentes) e, em um IDE moderno, não é tão difícil descobrir o tipo de algo.

Com a introdução das propriedades, não vejo necessidade de prefixar "_" nas variáveis ​​de instância da classe.Você pode definir uma regra simples (descrita em seu arquivo de cabeçalho) de que quaisquer variáveis ​​a serem acessadas externamente à classe devem ser acessadas por meio da propriedade ou usando métodos personalizados na classe para afetar os valores.Isso para mim parece muito mais limpo do que ter nomes com "_" colados na frente deles.Ele também encapsula adequadamente os valores para que você possa controlar como eles são alterados.

Não gosto de usar sublinhados como prefixos para quaisquer identificadores, porque C e C++ reservam certos prefixos de sublinhado para uso pela implementação.

Acho que usar "self.variable" é feio.

Em geral, eu uso identificadores simples (ou seja, sem prefixos nem sufixos) para variáveis ​​de instância.Se sua classe é tão complicada que você não consegue se lembrar das variáveis ​​de instância, você está em apuros.Então, para o seu exemplo, eu usaria "rect" como o nome da variável de instância e "newRect" ou "aRect" como o nome do parâmetro.

André:Na verdade, existem muitos desenvolvedores do Cocoa que não usam prefixos de variáveis ​​de instância.Também é extremamente comum no mundo Smalltalk (na verdade, eu diria que é quase inédito em Smalltalk usar prefixos em variáveis ​​de instância).

Prefixos em variáveis ​​de instância sempre me pareceram um C++-ismo que foi trazido para Java e depois para C#.Como o mundo Objective-C era em grande parte paralelo ao mundo C++, enquanto os mundos Java e C# são sucessores dele, isso explicaria a diferença "cultural" que você pode ver entre os diferentes conjuntos de desenvolvedores.

Meu estilo é híbrido e realmente um resquício da época do PowerPlant:

Os prefixos mais úteis que uso são "in" e "out" para parâmetros de função/método.Isso ajuda você a saber rapidamente para que servem os parâmetros e realmente ajuda a evitar conflitos entre parâmetros de método e variáveis ​​​​de instância (quantas vezes você viu o parâmetro "tabela" entrar em conflito com uma variável de instância de mesmo nome).Por exemplo.:

- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;

Então eu uso o nome simples para variáveis ​​de instância e nomes de propriedades:

Então eu uso "the" como prefixo para variáveis ​​locais:a tabela, o URL, etc.Novamente, isso ajuda a diferenciar entre variáveis ​​locais e de instância.

Depois, seguindo o estilo do PowerPlant, uso vários outros prefixos:k para constantes, E para enumerações, g para globais e s para estática.

Eu uso esse estilo há cerca de 12 anos.

Embora eu adore usar o prefixo de sublinhado para ivars, detesto escrever @synthesize linhas por causa de toda a duplicação (não é muito SECO).Criei uma macro para ajudar a fazer isso e reduzir a duplicação de código.Assim, em vez de:

@synthesize employee = _employee;

Eu escrevo isto:

ddsynthesize(employee);

É uma macro simples usando colagem de token para adicionar um sublinhado no lado direito:

#define ddsynthesize(_X_) @synthesize _X_ = _##_X_

A única desvantagem é que isso confundirá a ferramenta de refatoração do Xcode e não será renomeada se você renomear a propriedade por refatoração.

Junto com o que foi dito aqui, não deixe de ler a documentação do Cocoa sobre nomenclatura compatível com observação de valores-chave.Seguir rigorosamente esse padrão o ajudará muito no longo prazo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top