Tuesday, July 8, 2008

Sellme.ru (2 сообщения)

 rss2email.ruНа что подписаться?   |   Управление подпиской 

  RSS  Sellme.ru

http://sellme.ru
рекомендовать друзьям >>


  • Я люблю какао. Часть 3

    Языыык!!!

    Один пример, и я заткнусь (на сегодня). (Осторожно, заметка представляет из себя недефрагментированные мысли из головы.)

    Пишем метод, который берет такие параметры: имя файла (строка), надо ли сжимать файл (bool), и callback для индикации прогресса (указатель на метод). Как вызывать этот метод для объекта doc, с файлом test.txt, с компрессией и отсутствием коллбэка?

    C++:

    bool success = doc->WriteFile("test.txt", true, NULL);

    C#:

    bool success = doc.WriteFile("test.txt", true, null);

    Python:

    success = doc.write_file("test.txt", True, None);

    Ruby:

    success = doc.write_file("test.txt", true, nil);

    А теперь запустим симуляцию программера, который писал это ночью, проснулся к обеду и забыл про определение метода; посмотрим на код вызова. Что за хрени эти "test.txt", true и nil? Чего мы передаем в функцию? С именем файла вроде понятно, а остальное — это что?

    Вот что официальные правила кодирования на C++ в Google говорят:

    When you pass in NULL, boolean, or literal integer values to functions, you should consider adding a comment about what they are, or make your code self-documenting by using constants. For example, compare:

     bool success = CalculateSomething(interesting_value,                       10,                       false,                       NULL);  // What are these arguments?? 

    versus:

     bool success = CalculateSomething(interesting_value,                       10,     // Default base value.                       false,  // Not the first time we're calling this.                       NULL);  // No callback. 

    Бедные вечнокомментирующие гугловские программисты, так жаль их.

    Встречайте Objective-C:

    BOOL success = [doc writeFileToPath:@"test.txt" withCompression:YES callback:nil];

    Знаю, что глаза у вас затуманенны с непривычки. Вам подсветить?

    BOOL success = [doc writeFileToPath:@"test.txt" withCompression:YES callback:nil];

    Опа, нам не надо заглядывать в определение функции (или писать комментарий), потому что название метода уже содержит всю нужную информацию. Это именно название метода — writeFileToPath:withCompression:callback:, а не передача параметров в виде хэша/словаря, как это можно сделать в Ruby/Python.

    Вот, если хотите, большой метод:

     NSAlert *alert = [NSAlert alertWithMessageText:@"Passwords do not match" 			  defaultButton:@"OK" 			  alternateButton:nil 		 	  otherButton:nil 			  informativeTextWithFormat:@"Crap! Can you type?"]; 

    * * *

    Objective-C — компилируемый язык, всего лишь небольшая объектно-ориентированная надстройка над C (в отличие от C++, который совсем другой язык). Он динамический, и в нем не обязательно делать типизацию (NSString *myString — с типом, id myString — пофиг на тип).

    Одной из отличительных черт Objective-C является его динамизм — целый ряд решений, обычно принимаемых на этапе компиляции, здесь откладывается непосредственно до этапа выполнения.

    Ещё одной из особенностей языка является то, что он message-oriented в то время как С++ — function-oriented. Это значит, что в нём вызовы метода интерпретируются не как вызов функции (хотя к этому обычно все сводится), а именно как посылка сообщения (с именем и аргументами) объекту, подобно тому, как это происходит в Smalltalk-е.

    Такой подход дает целый ряд плюсов — так любому объекту можно послать любое сообщение. Объект может вместо обработки сообщения просто переслать его другому объекту для обработки (так называемое делегирование), в частности именно так можно легко реализовать распределенные объекты (то есть объекты находящиеся в различных адресных пространствах и даже на разных компьютерах).

    (википедия)

    С Objective-C можно делать многое интересное, что можно сделать с языками вроде Python и Ruby и нельзя сделать с языками типа C++. При этом, так как это Си с надстройкой, код можно смешивать: в Си-функциях использовать посылку сообщений ObjC объектам, а из ObjC-методов вызывать функции Си. В Objective-C 2.0 есть properties и (опциональная) сборка мусора.

    Товарищи, на этом языке писать — одно удовольствие!

    * * *

    Напоследок, еще немножко примеров с Google’овскими рекомендациями по C++:

    Doing Work in Constructors

    Do only trivial initialization in a constructor. If at all possible, use an Init() method for non-trivial initialization.

    * There is no easy way for constructors to signal errors, short of using exceptions (which are forbidden).
    * If the work fails, we now have an object whose initialization code failed, so it may be an indeterminate state.
    * If the work calls virtual functions, these calls will not get dispatched to the subclass implementations. Future modification to your class can quietly introduce this problem even if your class is not currently subclassed, causing much confusion.
    * If someone creates a global variable of this type (which is against the rules, but still), the constructor code will be called before main(), possibly breaking some implicit assumptions in the constructor code. For instance, gflags will not yet have been initialized.

    Decision: If your object requires non-trivial initialization, consider having an explicit Init() method and/or adding a member flag that indicates whether the object was successfully initialized.

    В Objective-C нет конструкторов по умолчанию, и принято писать init-методы: например, init, initWithFileName, initWithSomethingCool:doMore: и т.п. Создание объекта происходит таким образом: [[SomeClass alloc] initWithFileName:fileName]. Другой способ — метод класса, который сам возвращает инициализированный объект (см. пример с NSAlert выше).

    The #define Guard

    All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be project_path_file_H_.
    link
    To guarantee uniqueness, they should be based on the full path in a project’s source tree. For example, the file foo/src/bar/baz.h in project foo should have the following guard:

     #ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_  ...  

No comments: