воскресенье, 30 марта 2014 г.

Как важны мелочи

Я переписывала пример из книги. Управление классом Cursor взял на себя класс CursorLoader. Он должен был создавать объект, приводимый к типу Loader<Cursor> и позволять с ним работать. Но сперва у меня выдавалась ошибка компиляции. Я довольно долго не понимала, в чем дело. CursorLoader к нужному классу не приводился. Я думала, что в книге опечатка. Пошла в интернет. Там то же самое. Решила, что скорее всего, что-то не так у меня в коде. И оказалось, что для CursorLoader я указала неправильный пакет. Т.е. я пыталась использовать совершенно другую функцию,  с другими возможностями. Поэтому невозможно было приведение типов. Итак, призываю себя к вниманию, вниманию и еще раз к вниманию. Одна ошибка найдена и исправлена! Но программа все равно пока не работает(.

пятница, 28 марта 2014 г.

SQL в андроиде

Для хранения данных между программными сессиями в андроид используется встроенная база данных. Каждое приложение может создать там свои таблицы и будет иметь к ним доступ. Для работы с БД есть классы ContentProvider, Cursor, SQLiteOpenHelper. Я до сих пор не разобралась, для чего их так много и что они делают. Я тупо переписываю пример из книги в программу и никак не соединю части в одно целое. Может,  это потому, что вообще тема баз данных для меня сложная, т.к. я ее нормально не успела прослушать в институте. Пока я зависла на них. Переписывание примера до сих пор не закончено. Получается все по странице из книги в день в лучшем случае. Хотя, может быть, это просто потому, что переписывание меня не вдохновляет. Нужно взять себя в руки и допереписать. А потом править то, что уже надумалось. И пробовать широковещательные приемники и вызовы сторонних программ из приложения. Почему-то это меня больше вдохновляет. Хотя эта тема для меня такой же темный лес, как и БД.

понедельник, 17 марта 2014 г.

Пометки для себя

Уже второй раз в проекте бывает, что при прекомпиляции не могут быть подключены ресурсы. Их видно, класс R генерируется, но, например, если в ресурсах цвет для собственного представления, то это представление не отображается из-за ошибки. Мне кажется, что это глюк ноутбука т.к. после перезагрузки все становится нормально.

пятница, 14 марта 2014 г.

Переопределение и перегрузка

В Java как и в C++ возможна перегрузка методов. Т.е. возможно создать методы с одинаковыми именами и с разным набором параметров, так, что выбор нужного метода определяется входными параметрами. Так же возможно переопределение родительского метода в классе-наследнике. Для переопределения необходимо, чтобы и название метода, и его параметры соответствовали классу-родителю. Иначе вместо переопределения получится перегрузка. Для того, чтобы минимизировать количество ошибок, в языке Java есть аннотация @Override. В классе-наследнике перед методом, который нужно переопределить, ставится аннотация  @Override и компилятор выдает ошибку на этапе компиляции, если вместо переопределения получается перегрузка, т.е. если параметры метода, подлежащего переопределению не соответствуют параметрам метода в родительском классе.

пятница, 7 марта 2014 г.

Конец про класс и про методы.

Надо бы поместить про класс в предыдущий пост, но блоггер почему-то выдал ошибку, при попытке дописать в пост окончание главы. Поэтому она здесь. 

 Минимизация сложности класса:
  • Включайте в класс как можно меньше методов.
  • Неявно сгенерированные методы, которые не нужны, блокируйте.
  • Минимизируйте число разных методов, вызываемых классом.
  • Избегайте опосредованных вызовов методов из других классов.
 Несколько слов о конструкторах.
Инициализируйте по возможности все данные-члены!
Если нужен класс-одиночка - используйте синглтон.
Создавайте конструктор полного копирования, если сомневаетесь - для С++ это верно. Нужно ли это в Java, я не помню(.

Причины создания класса.
  • Моделирование объектов реального мира.
  • Моделирование абстрактных объектов.
  • Снижение сложности.
  • Изоляция сложности.
  • Сокрытие деталей реализации.
  • Ограничение влияния изменений.
  • Упрощение передачи параметров в методы - если несколько методов используют одни и те же данные, вероятно, их нужно выделить в класс.
  • Создание центральных точек управления.
  • Облегчение повторного использования кода.
  • Планирование создания семейства программ.
  • Упаковка родственных операций.
  • Выполнение специфического рода рефакторинга.

Методы.

Далее в книге идет целая глава, посвященная методам.
Причины создания методов во многом такие же, как и причины создания классов. И кроме этого, есть еще несколько:
  • снижение сложности;
  • формирование понятия промежуточной абстракции;
  • предотвращение дублирования кода;
  • поддержка наследования - т.к. переопределить небольшой грамотно спроектированный метод проще, чем длинный и плохо спроектированный;
  • сокрытие очередности действий;
  • сокрытие операций над указателями - неочевидная для меня причина, но очень разумная и приводящая к простоте написания программы;
  • улучшение портируемости;
  • упрощение сложных булевых проверок - мне раньше казалось, что наличие таких проверок - это показатель "крутости" кода, но они практически нечитаемы после написания и отладки; поэтому и с этой причиной я согласна; попытаюсь впредь делать так;
  • повышение быстродействия.
Проектирование на уровне методов - проектирование методов. Методы характеризуются связностью (или силой) - соответствием выполняемых в методе операций единой цели. Самый распространенный пример хорошего метода - операция cos() или sin(). Метод cosinAndTangens() - имеет худшую связность, т.к. выполняет сразу две операции.
Цель - чтобы один метод эффективно решал одну задачу и больше ничего не делал.

Имена методов.
Имя метода должно ясно описывать все, что он делает. Т.к. ясно именовать методы в институте не учат, подробно пишу главу из книжки. Далее будет набор правил, позволяющих дать методу понятное имя. Общее правило - если метод трудно назвать, скорее всего, он плохо спроектирован.

  • Описывайте все, что метод выполняет
  • Избегайте невыразительных и неоднозначных глаголов
  • Не используйте для различия методов исключительно номера (method1 (), method2 ()...)
  • Не ограничивайте длину имени методов искусственными правилами - имя метода длиннее имени переменной; главной задачей имени является ясное и понятное описание сути метода.
  • Для именования функции используйте описание возвращаемого значения.
  • Для именования процедуры используйте выразительный глагол ( дополняя его объектом, если язык не ОО).
  • Определяйте конвенции именования часто используемых операций.
  • Дисциплинированно используйте антонимы. Т.к. это тоже одно из моих больных мест, пишу здесь часто используемые:
add/remove
begin/end
create/destroy
first/last
get/put
get/set
increment/decrement
insert/delete
lock/unlock
min/max
next/previous
old/new
open/close
show/hide
sourse/target
start/stop
up/down

Желательно, чтобы длина метода была не более 150-200 строк(без комментариев и пустот), обычно метод занимает до 100 строк. Если метод хорошо спроектирован, он уложится в эти рамки (должен).

Функцию следует использовать тогда, когда главной целью метода является возврат конкретного значения, описываемого именем функции.

Про макросы. 
Опять же, программируя на С++ я думала, что использовать макросы - это показатель крутости. Но их использование давало иногда такие ошибищи которые очень трудно было отследить и понять.  Макконнелл не рекомендует использовать макросы, кроме как в условной компиляции (он ссылается в этом на Страуструпа, а тот, видимо, знает, что говорит)).

Итак, ура. Глава, посвященная методам обработана. Надеюсь, я буду это все использовать. Очень часто при чтении этой книги у меня возникают мысли: а, как просто-то, а я... Учиться мне еще и учиться...

суббота, 1 марта 2014 г.

Наследование. Продолжение.

Наследование. Отношение "Является".
  • Убедитесь, что вы наследуете только то, что хотите наследовать. Не наследуйте реализацию только потому, что вы наследуете интерфейс. Если интерфейс класса не нужен, а нужна лишь реализация, то лучше включение, а не наследование.
  • Не используйте имена непереопределяемых методов базового класса в производных классах.
  • Перемещайте общие интерфейсы, данные и формы поведения на как можно более высокий уровень абстракции. 
  • С подозрением относитесь к классам, объекты которых создаются в единственном экземпляре. Исключение - "Одиночка".
  • С подозрением относитесь к базовым классам, имеющим только один производный класс.
  • С подозрением относитесь к класам, которые переопределяют метод, оставляя его пустым (убирая реализацию).
  • Избегайте многоуровневых иерархий наследования.
  • Предпочитайте полиморфизм, а не крупномасштабную проверку типов.
  • Множественное наследование - "инструмент, который лучше большую часть времени хранить в гараже под замком". Может пригодится, но может и порождать ошибки (ромбовидная схема!).
Правила, чтобы понять, нужно ли проектировать классы как наследники или включения.
Если несколько классов имеют общие данные, но не формы поведения, сделайте общий объект, который включите в эти классы.
Если несколько классов имеют общие формы поведения, но не данные, сделайте эти классы производными от общего базового класса, определяющего общие методы.

вторник, 25 февраля 2014 г.

Продолжаю конспектировать "Совершенный код".
Раздел "Вопросы проектирования и реализации".
Класс может содержать данные или другой класс. Это отношение "Включение".
  1. Реализуйте с помощью включения отношения "Содержит".
  2. В самом крайнем случае такое отношение может быть реализовано с помощью закрытого наследования -  автор считает, что если получается только так, то это ошибка проектирования и что лучше всего еще раз подумать. Наверное, он прав. Я с таким на практике еще не сталкивалась.
  3. Настороженно относитесь к классам, содержащим более 7+\-2 данных-членов. Автор считает, что можно класс, содержащий много данных разбить на несколько классов, содержащих небольшое количество данных, и что это поможет упростить работу с данными. Опять же, нужно проверить на математике "Mittens".
Теперь наследование.
"Цель наследования - создать более простой код, что достигается путем определения базового класса, идентифицирующего общие элементы двух или более производных классов."
  1. Реализуйте при помощи открытого наследования отношения "является". Если производный класс не будет полностью придерживаться контракта, наследоваться не надо.
  2. Проектируйте и документируйте классы с учетом возможности наследования или запретите его.
  3. Соблюдайте LSP: клиенты должны иметь возможность использования подклассов через интерфейс базового класса, не замечая никаких различий. Если программист, сделав наследование, забывает о деталях реализации наследников - все ОК. Если он должен думать о семантических различиях реализаций подклассов - наследование зло, тк. не способствует снижению сложности. 
Продолжение следует...