Принцип KISS гласит: делай настолько просто, чтобы проще было некуда.
Вопрос в том, что такое «проще». Вместо классов использовать дополнительные поля и ветвить логику? Или, наоборот, использовать полиморфизм? Однозначного ответа тут нет.
Зато есть хороший принцип третьего дублирования: если что-то хочешь продублировать в третий раз — пора с условий перейти на полиморфизм.
А заранее создавать абстрактные фабрики, отвязывание по интерфейсам и инъекции — это, естественно, усложнение, а не упрощение. А главная причина создания ООП как раз была в упрощении.
Так что, люди, используем исконные принципы ООП, а паттерны, архитектуры и т.д. — только если они упрощают жизнь.
P.S. IMHO, оба приведенных в статье примера сложны. Первый — чрезмерной абстрактностью и гибкостью, второй — слишком большим количеством условий и логики на нетипизированных данных, собранным в одном месте. Истина где-то между.
Не обязательно из среди программистов.
Чтобы понимать принципы и взаимосвязи, необязательно быть разработчиком.
Единственное требующееся умение — понимание программистов.
Менеджер должен учитывать особенности каждого разработчика команды, в том числе касающиеся оценки, и приводить их к общим показателям (суммирующим, средним и т.д.).
Это не отменяет того, чтобы самому для себя развиваться и в качестве грамотного оценщика. Более того, если хочешь из программиста стать архитектором, тебе это необходимо как воздух.
Не стоит держать компилятор за дурака.
Он умнее нас вместе взятых.
Его несколько лет писали очень умные люди.
И тщательно проводили оптимизации генерируемого кода.
Советую профилировать или смотреть сгенерированный байт-код, прежде чем делать предположения о производительности.
На самом деле, я думаю, много кому будет интересно и полезно вспомнить, что находится под капотом :-)
В нашем деле про это лучше не забывать, потому что там есть ответы на все вопросы, на которые уровнем выше ответа может и не найтись.
Кстати, это одна из причин, почему нельзя сделать так:
public class SuperClass<T> {
public void setT(T obj) {
//...
}
}
public class SubClass<Number> extends SuperClass<Number> {
// Здесь будет ошибка компиляции, т.к. метод с такой сигнатуров уже есть
public void setT(Object obj) {
//...
}
public void setT(Number obj) {
//...
}
}
Потому что generic'и требуют объекта в качестве параметра.
А упирается это в генерацию кода, совместимого с Java 1.4.
Реально в runtime вместо типа T подставляется ближайший тип, прописанный в extends, и используются приведения типов. Они, естественно, будут безопасными, т.к. компилятор уже все проверил.
IMHO, решать проблему надо в корне.
generic'и нужно заменить на template'ы с поддержкой примитивных типов.
А если следовать парадигме обратной совместимости, то добавить рядом.
Синтаксис различимый вполне можно сделать.
Преобразование между ними — тоже.
Зато приседаний станет гораздо меньше.
Кстати, поскольку проблемы с многопоточностью идут от разделяемых данных, часто используют концепцию очередей, когда данные одного потока «привязываются» к событию в очереди, и потом поток-получатель события получается эти данные.
Существует множество хороших решений для реализации очередей, так что можно просто использовать готовое решение, вся сложность многопоточных блокировок спрячется под капот, и останется только следовать event-oriented парадигме.
Любое изменение кода со сложным управлением многопоточностью должно проводиться под микроскопом.
Желательно с формальным доказательством а-ля happens-before.
В стандартных UI-компонентах Delphi очень плохо с инкапсуляцией.
Вплоть до того, что можно штатным, нормальным использованием интерфейса класса получить Exception. (!)
IMHO, в C# и Java с этим гораздо лучше.
Вопрос в том, что такое «проще». Вместо классов использовать дополнительные поля и ветвить логику? Или, наоборот, использовать полиморфизм? Однозначного ответа тут нет.
Зато есть хороший принцип третьего дублирования: если что-то хочешь продублировать в третий раз — пора с условий перейти на полиморфизм.
А заранее создавать абстрактные фабрики, отвязывание по интерфейсам и инъекции — это, естественно, усложнение, а не упрощение. А главная причина создания ООП как раз была в упрощении.
Так что, люди, используем исконные принципы ООП, а паттерны, архитектуры и т.д. — только если они упрощают жизнь.
P.S. IMHO, оба приведенных в статье примера сложны. Первый — чрезмерной абстрактностью и гибкостью, второй — слишком большим количеством условий и логики на нетипизированных данных, собранным в одном месте. Истина где-то между.
Создание сайта и десктопного приложения Вы имели в виду?
Если что, то сайт — это тоже приложение. Браузерное.
Крыша едет неспеша… (с)
Чтобы понимать принципы и взаимосвязи, необязательно быть разработчиком.
Единственное требующееся умение — понимание программистов.
Это не отменяет того, чтобы самому для себя развиваться и в качестве грамотного оценщика. Более того, если хочешь из программиста стать архитектором, тебе это необходимо как воздух.
Он умнее нас вместе взятых.
Его несколько лет писали очень умные люди.
И тщательно проводили оптимизации генерируемого кода.
Советую профилировать или смотреть сгенерированный байт-код, прежде чем делать предположения о производительности.
В нашем деле про это лучше не забывать, потому что там есть ответы на все вопросы, на которые уровнем выше ответа может и не найтись.
А упирается это в генерацию кода, совместимого с Java 1.4.
Реально в runtime вместо типа T подставляется ближайший тип, прописанный в extends, и используются приведения типов. Они, естественно, будут безопасными, т.к. компилятор уже все проверил.
generic'и нужно заменить на template'ы с поддержкой примитивных типов.
А если следовать парадигме обратной совместимости, то добавить рядом.
Синтаксис различимый вполне можно сделать.
Преобразование между ними — тоже.
Зато приседаний станет гораздо меньше.
Без этого комментария мысль была неполной.
На тяжелых, конструируемых объектах это бывает необоснованно.
Да и времени всегда не хватает на исследования, увы.
Существует множество хороших решений для реализации очередей, так что можно просто использовать готовое решение, вся сложность многопоточных блокировок спрячется под капот, и останется только следовать event-oriented парадигме.
Желательно с формальным доказательством а-ля happens-before.
Вплоть до того, что можно штатным, нормальным использованием интерфейса класса получить Exception. (!)
IMHO, в C# и Java с этим гораздо лучше.