Элегантность окупается всегда. Элегантность не только позволяет вам проще создавать или отлаживать программу, но и проще ее понять и обслуживать в дальнейшем, что очень положительно сказывается на финансах.
Сначала пускай он работает, а затем сделаем его быстро работающим. Дайте системе сначала наивозможно простую модель. Затем, если нужные участки не достаточно быстры, то оптимизируйте их. Затем вы уже всегда будете понимать, действительно ли это узкое место или все-таки нет.
Помни принцип "Разделяй и властвуй". Разбейте код на объекты, напишите код, использующий эти объекты, а сложные части инкапсулируйте в другие объекты и т.д.
Отделяй создателя класса от пользователя класса (клиентское программирование). Пользователь класса - простой потребитель, он не должен знать что именно и как происходит внутри ваших классов. Создатель класса должны быть экспертом в создании и проектировки классов, поэтому получаемый класс должен быть максимально прост в использовании.
Когда Вы создаете класс, старайтесь дать ему имя такое, что бы не нужны были комментарии. Ваша задача сделать интерфейс клиентского программиста концептуально простым. Для этого используйте перегрузку методов, когда нужно и легкий в использовании интерфейс.
Ваша модель системы должна производить по минимуму классов, интерфейсов и связей с другими классами, в частности с базовыми. Избавляться от ненужных частей проекта, что существенно сказывается на их производительности.
Автоматизируй все! Пишите тестовый код в первую очередь (до того, как напишите сам класс) и сохраните его вместе с классом. Автоматизируйте запуск ваших тестов посредством makefile или др. Тогда любые изменения в коде могут быть автоматически проверены запуском теста, а Вы при этом немедленно получите все ваши ошибки
Пишите сперва тестовый код, до того, как Вы напишите ваш класс, в порядке проверки правильности проектировки.
Создавайте классы настолько атомарными, на сколько это возможно. Давайте каждому классу простое, понятное предназначение. Ключи для предположения по перепроектировке класса: 1) Запутанные операторы: подумайте о полиморфизме. 2) Большое число методов, которые обрабатывают различные типы или операции: подумайте о нескольких классах. 3) Большое число элементов переменных, которые относятся к различным характеристикам: подумайте о нескольких классах.
Следите за длинными списками аргументов. Попробуйте переместить метод в класс, где его наиболее часто употребляют или передавайте ему объекты, как аргументы.
Не повторяйтесь. Если некий кусочек кода требуется в многих методах дочерних классов, то поместите его в один метод базового класса, а затем вызывайте его из дочернего.
Следите за выражениями switch и цепочками if-else. Вы должны заменять этот код посредством наследования и полиморфизма; вызовы полиморфных методов выполняют за вас всю работу по проверке типов, что в результате позволяет иметь более гибкую систему.
С точки зрения проектировки, найдите и отделите те вещи, которые могут изменяться от тех, которые всегда постоянны. Это означает, что нужно в системе найти элементы, которые Вы можете изменить без принудительного редизайна, затем инкапсулируйте их в отдельные классы
Не расширяйте фундаментальную функциональность посредством подклассов. Если элемент интерфейса для класса важен, то он должен быть в базовом классе, а не добавлен в процессе наследования. Если же Вы добавляете методы во время наследования, то стоит подумать о перепроектировке.
Меньше - больше. Начинайте с минимума интерфейса класса, что бы только хватало решить поставленную задачу. Как только ваш класс будет использован, то здесь уже можно посмотреть и расширять его интерфейс. Если вам нужно расширить интерфейс создайте перегруженный метод с новыми аргументами.
Во время принятия решения по использованию наследования или композиции, спросите себя, а нужно ли мне использовать приведение к базовому типу? Если нет, то предпочтите композицию наследованию.
Используйте иерархию исключений, желательно наследовать от специального класса в стандартной иерархии исключений Java.
Иногда простая агрегация выполняют всю работу. Вы должны просто создать публичные элементы-объекты. Эти объекты имеют свою собственную реализацию, но при этом они так же безопасны
Примите во внимание клиентского программиста и того, кто будет обслуживать ваш код. Проектируйте ваш класс настолько ясно, насколько это возможно для использования.
Остерегайтесь синдрома гигантских объектов.
Сперва используйте композицию, когда создаете новый класс от уже существующего. Вы должны использовать наследование только, если это требование вашего дизайна.
Используйте шаблоны проектировки, что бы исключить "голую функциональность". Исключение "голой функциональности"(много грязного кода в вашей главной программе,) не только сделает ваш код более легким для понимания и поддержки, оно так же сделает его более пуленепробиваемым против "доброжелателей" пришедших после вас.
Остерегайтесь аналитического паралитизма. Запомните, что Вы должны обычно продвигаться вперед в проекте до того, как Вы узнаете все о нем, а лучшим способом при этом будет узнавать то, что Вы не знаете до того, как Вы к этому приступите
Когда Вы думаете, что Вы хорошо проанализировали систему, создали отличный проект или его реализацию, то критично оцените (проанализируйте ее сквозным методом) всю систему целиком. Покажите систему какому - либо стороннему лицу, кто не участвовал в разработке или консультациях.
14. Основные правила «хорошего» объектно-ориентированного проектирования (Реализация)
В основном следуйте условностям кодирования от Sun-а. Эти принципы используются для большого числа программ и большим числом программистов. Если же Вы будете упорно использовать свой собственный стиль написания, то Вы доставите немало трудностей читателю ваших исходных кодов. Но все равно, тот стиль кодирования, который Вы предпочитаете должен соблюдаться на протяжении всего проекта.
Независимо от того, какой стиль кодирования Вы используете, стиль исходного кода будет различаться в вашей команде или целиком в вашей компании. Это означает, что следует приводить стиль написания к некоему общему стилю
Следуйте стандартным правилам капитализации (изменения регистра). Капитализируйте первые буквы имен классов. Первые буквы полей, методов и объектов должны начинаться с маленькой буквы. Все идентификаторы должны содержать все слова вместе с большими буквами в начале каждого из слов. К примеру: ThisIsAClassName, thisIsAMethodOrFieldName. Капитализируйте все буквы staticfinal примитивов, который были проинициализованы в константы при их определении. Это будет означать, что они константы времени компиляции.
Не создавайте своих собственных, оформленных частных членов данных. Часто это выражается в виде висячих строк и символов.
Следуйте каноническим формам при создании классов для основного использования. Включайте в него определения для equals(), hashCode(), toString(), clone() (реализуйте Cloneable) и реализуйте Comparable и Serializable.
Используйте JavaBean-овые "get", "set" и "is" соглашения об именовании для методов, которые читают и изменяют поля private, даже если Вы думаете, что этому компоненту не жить долго. Это не только позволит использовать этот класс как Bean, это так де и стандартный путь именования такого рода методов, что несомненно же позволит читателю более легко разобраться в исходном коде.
Рассмотрите возможность поместить в каждый из классов, который Вы создаете метод static public test(), который позволяет тестировать ваш класс. Вам не нужно удалять этот тестовый код из класса в проекте, но а когда Вы что-то измените, то можно с легкостью его протестировать. Этот же код может служить так же и примером по использованию вашего класса.
Иногда вам требуется наследовать, что бы получить доступ к защищенным элементам базового класса. Это может привести к необходимости восприятия множественных базовых типов. Если же вам не нужно приводить к базовому типу, тогда сперва создайте новый дочерний класс для доступа к закрытым областям родительского класса. Затем сделайте этот новый класс элементом внутри любого другого класса, которому требуется использовать эти данные, прежде чем наследовать.
Избегайте использования final методов в целях эффективности. Используйте final только если программа работает не так быстро как хотелось бы, а ваш профайлер показывает, что именно в этом месте и есть то самое бутылочное горлышко.
Если два класса взаимосвязаны между собой функционально (контейнерно или итерационно), то попытайтесь сделать один из них внутренним классом другого. При этом будет не только предано специальное значение связи этих двух классов, но и появится возможность повторного использования класса внутри отдельного пакета вложением его в другой класс
Не станьте добычей преждевременной оптимизации. Этот путь сравни сумасшествию. В частности, не беспокойтесь о написании (или не написании) нативных методов, создания некоторых методов с модификатором final или настройкой кода для создания эффективной системы. Ваша основная задача - реализовать проект, с наибольшей эффективностью дизайна.
Используйте контейнеры в стандартных библиотеках Java. Становясь более профессиональным с использованием контейнеров, Вы еще к тому же значительно повысите вашу производительность. Предпочитайте ArrayList для последовательностей, HashSet для наборов, HashMap для ассоциативных массивов, а LinkedList для стеков (а не Stack) и очередей.
Для программы, которая должна быть "крепкой", каждый их компонентов должен быть "крепким". Используйте все инструменты представляемые Java: управление доступом, исключения, проверка типов и т.д. для каждого класса, который Вы создаете. При этом вы сможете перейти на следующий уровень абстракции при создании вашей системы.
Предпочтите ошибки времени компиляции ошибкам времени выполнения. Попытайтесь обработать все ошибки по максимуму. Обрабатывайте ошибки на месте возникновения исключения.
Остерегайтесь длинного описания методов. Методы должны быть кратки, а функциональный модуль описывать и реализовать дискретную часть интерфейса класса. Длинный и сложный метод труден для понимания и вызывает большие расходы при выполнении, и кроме этого он пытается сделать слишком много для одного метода.Так же можно предложить создать и новый класс для этих методов
Сохраняйте все как можно более частным образом (private). Ограничение видимости играет большую роль при работе с потоками, только private поля могут быть защищены против несинхронного использования.
Используйте комментарии не стесняясьИзбегайте использования "магических чисел", которые жестко зашиты в код. Вместо этого, создавайте константы с описаниями и используйте их в своей программе. При этом вашу программу будет легче понять и опять же легче в последствии поддерживать.
Когда создаете конструкторы, не забывайте об исключениях. В лучшем случае, конструктор не должен ничего делать такого, что могло бы вызвать исключение.
Когда Вы переопределяете finalize() во время наследования, не забывайте вызывать super.finalize(). (Это не важно, если Object прямой родитель вашего класса.) Вы должны вызывать super.finalize() как завершающую часть вашего переопределения finalize() а не раньше, что бы быть уверенным, что объекты базового класса все еще валидны.
Когда Вы создаете контейнеры фиксированного размера для объектов, то передавайте их как массивы если Вы возвращаете эти контейнеры из методов. При этом у вас будет возможность осуществлять проверку типов времени компиляции, а получатель массива может не заботиться о приведении к базовому типу. Заметьте, что базовый класс контейнерной библиотеки java.util.Collection, содержит целых два метода toArray().
Выбирайте интерфейсы перед абстрактными классами. Если Вы знаете, что что-то собирается стать базовым классом, вам бы следовало сперва сделать его как interface, а только если Вы решаетесь включить в него определения методов и переменных, то сделайте его abstract классом. Interface декларирует, что клиент должен делать, а класс концентрирует внимание на деталях реализации.
Что бы не набраться большого опыта по срыву проектов, убедитесь, что в classpath существует только по одному экземпляру распакованного класса (уникального).
Берегитесь случайной перегрузки. Если Вы решились переопределить метод базового класса, но при это Вы сделали небольшую ошибочку, то вам, лучше прервать редактирование нового метода и начать сначала. Поскольку при этом ошибки может и не быть, а вот метод работать правильно уже не будет.
Запомните, что код больше раз читается, нежели пишется. Читая проектировка создает легко понимаемые программы, но все таки без комментариев и разъяснения деталей они будут не очень понятны. А проектировка и комментарии к ней с разъяснениями помогут вашим последователям, кто придет после вас.