Category: общество

Category was added automatically. Read all entries about "общество".

Работа, Java

Объекты и модели

Странным образом прервалась череда недовольств по Андроиду. Ну что поделать, лень писать о том, что и так понятно.

Я все время думал, почему некоторые люди быстро пишут большие куски программы, в которых все просто и понятно, а у других получается неповоротливый монстр, который еще и работает как попало. Теперь я понял, в чем проблема. Смешно, но проблема у всех одна - не понимание основополагающих принципов ООП. Тезис простой: "Грамотно построенная объектная модель, сокращает время разработки в несколько раз". Конечно, MVC никто не отменял, но это уже техника, базовое умение правильно распределить обязанности тех или иных сущностей избавит вас от многих проблем. Не знаете, как их распределить - воспользуйтесь шаблонами и наработками старших программистов вашей компании. Соблюдение минимальных правил и правильное деление на функции - вот все, что нужно для успешной реализации View и Controller. Я, конечно, не спорю, что при написании Framework-ов для View и Controller архитектура встает в полный рост - но на то они и Framework-ки - универсальные инструменты разработчика. Я же сейчас разговариваю в рамках написания программ. Как правило, framework для работы с визуальными компонентами уже есть и на его готовой архитектуре легко писать расширения, а для слоя управления, можно применить универсальный метод, базирующийся 2-х или 3-х принципах, поэтому проблемы это не составляет, так что вернемся к модели.

Первые грабли, на которые наступают все новички - это строят модель, базируясь на формате предоставленных данных. К сожалению, данные могут быть предназначены для совершенно другого и не всегда сервисы пишутся грамотными людьми в условиях достаточного (для осознания полной картины) времени специально для вашей программы. Только выполнение этих трех условий может гарантировать вам правильную модель. Рассмотрим невыполнение каждого из условий.

  • Попался неквалифицированный специалист. Он, так же как и вы, будет писать ОМ на основе чего-то другого. Как правило, такие люди говорят что-то вроде "Мне так удобнее" или "Я не могу сделать по-другому". По сути, они навязывают вам не отвечающий требованиям вашей программы интерфейс и даже чем-то мотивируют свои недоделки. Задайте себе вопрос "Кто пишет программу? Я или он?" Наверняка, вы лучше понимаете, что именно вам нужно в данных, а что не нужно.
  • У человека нет времени. Тут все ясно. Он не будет сидеть и обсуждать с вами, как именно надо организовать модель что бы вам было проще работать. Он просто будет по факту исполнять запрос за запросом от руководителя проекта, а что получится в результате - его не волнует.
  • Сервис пишется не для вашей программы. Здесь все и так понятно. Зачем вам знать про количество оборотов на холостом ходу Toyota Camry после заправки 95 бензином, если вы пишите приложение по поиску автозаправочных станций или продаже машин.
  • Есть еще четвертый вариант - объектная модель имеет довольно сложную и не представимую в виде дерева структуру, что передать их через протокол, основанный на JSON или XML, будет довольно сложно, но тут, как правило, хотя бы, сущности выделятся верно. Другое дело, что связей нет, но это не так страшно.

Так что, лучший способ писать приложение - начинать с анализа интерфейса. Как правило, тот или иной экран в приложении не будет использовать больше 3-4 классов. Ему это не за чем. И даже если используется больше - они должны быть тесно связанны. В идеале - ссылаться друг на друга. Если экран содержит 2 разрозненные группы объектов с данными, он легко и логично бьется на 2 части, которые будут работать сами по себе и представлять 2 разных экрана. Второй момент - это Flow. В данном случае множество экранов, можно считать одним большим, который подчиняется предыдущему закону. Не забывайте о наследовании и инкапсуляции. Наследование помогает построить иерархию, объединяя классы в группы, а инкапсуляция избавит от лишних багов.

И так, чем же опасна неверная модель?

  • Контроллеры будут вынуждены постоянно конвертировать данные из одного формата в другой и обратно. Много кода будет написано по этому поводу. Зачем, если можно конвертировать только один раз.
  • Другим людям будет сложнее понять логику вашего приложения или компонента. Особенно эта проблема встречается когда визуально одни и те же данные присутствуют в разных частях модели и невозможно понять какая именно часть нам нужна.
  • Появляется множество потенциальных багов, причем как правило они размазаны по всему коду и ловить их очень сложно. Примером может служить неожиданные изменения в логике, или неправильный алгоритм преобразования данных.
  • Увеличивается количество объектов живущих в каждый момент времени, что приводит к уменьшению производительности системы в целом и крахом при малейших попытках украсить приложение новыми рюшечками или анимированным переходом. (конечно можно использовать GodObject, но номинальное количество объектов не так страшно, как страшен объем который они занимают в памяти)
  • Отсутствуют явные ссылки между объектами, что приводит к ужасным алгоритмам поиска по спискам, плюс к тому, не всегда понятно что искать.
  • Появляется большая избыточность в данных - и куча клонированных методов, которые могут образовывать страшную паутину зависимостей, что в дальнейшем вашу программу проще будет выкинуть и написать с нуля, чем выводить ее на следующий этап разработки.

Страшнее всего тем компаниям, где программисты ушли в "свободное плаванье", т.е. каждый имеет свою зону ответственности, и в нее никто не лезет, пока не настал полный ***. И тут уже есть 2 варианта развития. Первое, забиваем на все и тупо правим визуальные косяки, как можем. Если же не можем либо в дальнейшем планируется, что называется, "продолжение банкета" то выкидываем код и пишем с нуля (как правило, переиспользовать куски старого на этот момент уже нереально). Возможен и третий вариант, когда вначале титаническими усилиями TeamLead-ов мы таки доводим проект до сдачи, а потом сажаем виновников на повторное написание, предварительно прочитав лекцию длинною в несколько часов почему именно они не правы. (цензурность высказываний зависит от лектора, но я бы не советовал особо ей изобиловать в отношении тех кому собственно эта лекция предназначена)

Резюмируя то, что я сказал, добавлю следующее. При разработке любого куска приложения, сложнее "Hello World", в команде должен присутствовать опытный разработчик. И именно он должен писать объектную модель. Больше он может ничего не делать, но это решение сократит время разработки в несколько раз, а главное уменьшит шанс провалить проект.

Ну и напоследок - основные ошибки, как я их вижу.

  • "Внутренности наружу" все очень просто, структура данных не скрыта за объектной оберткой.
  • "Порочный эффект" при вызове какого-нибудь метода у объекта из модели, неявно меняется конфигурация системы.
  • "Строковая дата" поля объекта имеют не тот тип. К примеру, у объекта есть поле date, по которому они сортируются, и оно хранится в виде строки.
  • "Дубль два" появление дубликатов объектов
  • "Мы не знакомы" полное отсутствие каких-либо связей.
Android

Андроид. Глава 2.

И так продолжим.
Значит с понятием Interface Bulder для Android разобрались. Его тупо нет. Хотя я думаю, что если бы Google задался этим вопросом в серьез, то они бы сделали его правильно и красиво. В конце-концов есть масса положительных примеров, которыми люди пользуются с удовольствием. Но не в этом дело. Мое отношение к встроенному в Eclipse IB - он просто есть. Как есть еще 1000 никому не нужных библиотек. Другое дело это Debug. Во первых, почему все пишущие на C/C++ люди так любят Breakpoint-ы? Нет, я ничего против не имею, но есть одно но, Java не особо позитивно относится к этим вещам, ибо они превращают ее в интерпритируемый язык. Да и система Exception-ов не зря придумана. И наличие StackTrace-а в них тоже не случайно. 99% ошибок Java-ского flow ловится при помощи правильного написания логов и анализа StackTrace-ов. В любом случае народ активно доказывал мне, что Eclipse круче по причине наличия в нем debug-ера. (замечу что IntelliJ Idea 9, также имеет полноценную поддержку Android со всеми Eclipse-овыми приблудами)

Резюмируя все вышесказанное заключу - для Java-ской разработки под Android не важно в какой Ide писать. Хотя если слова XML и Layout вызывают у вас легкий страх - садитесь на Eclipse. Или даже не садитесь, а изучайте как выращивать комнатные растения, а разработку приложений оставьте профессионалам.

Следующий сюрприз, с которым я столкнулся - автогенеренный класс. Я долго тупил над классом с названием R, который содержал в себе еще несколько статических подклассов. Оказалось, что это просто статически прописываемые ссылки на ресурсы, (просто гениально, и зачем придумали stream-ы и методы типа Class.getRecourceAsStream(String)) которые скармливаются всем кому не поподя начиная непосредственно с RecourceManager-а, и заканчивая медиаплеерами и прочей системной ерундой. Хорошо хоть догадались оставить классические методы. У меня тогда возник вопрос, а что делать когда надо как-то категоризировать ресурсы, ответ оказался очевиден - ничего. Ну не поддерживает платформа разбиение рисунков на подкатегории. Более того, не дай бог тебе положить ресурс с левым именем или содержанием не в ту папку. Ты будешь проклят в веках и твое приложение никогда не соберется. С одной стороны - хорошо, приучает программистов не складывать в одну кучу изображения, XML layout-а и пр ерунду, но где полное описание того, что куда можно положить, что бы этот ежик полетел? (про документацию от google поговорим позже) Где возмоность разбить графику или layout по категориям? В результате таких художественных изысков ресурсы именуются типа "about_screen_header_back_button_image_unfocused.png", что естественно не дает легко и непринужденно читать не только код, но и названия самих файлов.
В принципе, графики в проектах обычно немного и это можно пережить. (Хотя, когда приложение состаит из 3-4 независимых flow, каждое из которых насчитывает около десятка различных экранов, должен появиться легкий дискомфорт. Подобное приложение я писал на Blackberry, и эти flow я разделил изначально.) гораздо интереснее дела обстоят с ID компонентов. Представьте себе, что они тоже все складируются в единой куче. С другой стороны, кажется - зачем ноно все нужно? Зачем вообще нужны ID? Объясняю, я еще ни разу не встречал экранных форм со статическим контентом (разве что экраны с информацией о каком-то действии или приложении, или заставки в приложениях) всегда надо как-то управлять элементами, начиная от навешивания событий на нажатие кнопок, и заканчива анимированным показом слайдов. Везде надо получать ссылки на компоненты, для чего и нужны ID. А тепеь пердставьте - у вас в программе 10-15 экранов (нормальные информационные приложения насчитывают и больше) И каждый содержит 5-7 элементов, которыми надо управлять. И того минимум 50 ID падает в единую кучу. У меня не получилось вписать все имена в 20 символов. Более того, под конец я стал путаться в именованиях. Вобщем - идея хорошая, но реализация сырая до безобразия.

Продолжая разговор о ресурсах, отвечу еще на пару вопросов, которые могли бы возникнуть у нормального человека. Первое, что делать, если тебе вдруг понадобились ресурсы формата не поддерживаемого в Android. Например doc, rtf или вообще свой формат. Ответ прост. В Android проекте папка с ресурсами содержит папку raw. также плоскую папку с ресурсами, которые никак не проверяются, но при этом, так же как и остальные, имеют свои уникальные ID. (Написал и задумался, а имеют ли? Не верьте мне на слово, если нужно будет проверьте при случае.) Так же помимо res есть папка assets, куда складываются "классические" ресурсы. Все это безобразие управляется 2-мя менеджерами представленными в классах Recources и AssetManager. Но будьте осторожны, добывать эти классы стоит непосредственно из Activity, Или другого наследника Context, доступного вам. второй вопрос - доступны ли нам ресурсы самой платформы. т.е. стандартные градиенты, иконки и пр вкусности. Ответ - да, для этого есть класс android.R
Продолжение следует...