Я начинаю проект школьной группы на Java, используя Swing. Это простой графический интерфейс для настольного приложения базы данных.
Профессор дал нам код из прошлогоднего проекта, чтобы мы могли видеть, как он работает. Мое первоначальное впечатление состоит в том, что код гораздо сложнее, чем должен быть, но я представляю, что программисты часто думают об этом, глядя на код, который они не просто пишут.
Я надеюсь найти причины, почему его система хороша или плоха. (Я спросил профессора, и он сказал, что я увижу позже, почему так лучше, что меня не устраивает.)
По сути, чтобы избежать какой-либо связи между его постоянными объектами, моделями (бизнес-логикой) и представлениями, все делается с помощью строк. Постоянные объекты, которые хранятся в базе данных, являются хеш-таблицами строк, а модели и представления «подписываются» друг на друга, предоставляя строковые ключи для «событий», на которые они подписываются.
Когда событие инициируется, представление или модель отправляет строку всем своим подписчикам, которые решают, что делать для этого события. Например, в одном из методов слушателя действия views (я полагаю, это просто устанавливает bikeMakeField на постоянный объект):
else if(evt.getSource() == bicycleMakeField)
{
myRegistry.updateSubscribers("BicycleMake", bicycleMakeField.getText());
}
Этот вызов в конечном итоге попадает в этот метод в модели Vehicle:
public void stateChangeRequest(String key, Object value) {
... bunch of else ifs ...
else
if (key.equals("BicycleMake") == true)
{
... do stuff ...
Профессор говорит, что этот способ работы более расширяемый и поддерживаемый, чем просто представление, просто вызывающее метод объекта бизнес-логики. Он говорит, что между взглядами и моделями нет связи, потому что они не знают о существовании друг друга.
Я думаю, что это худший тип связывания, потому что для работы и представление, и модель должны использовать одни и те же строки. Если вы удалите представление или модель или сделаете опечатку в строке, вы не получите ошибок компиляции. Это также делает код намного длиннее, чем я думаю.
Я хочу обсудить это с ним, но он использует свой отраслевой опыт, чтобы противостоять любым аргументам, которые я, неопытный студент, мог бы выдвинуть. Есть ли какое-то преимущество в его подходе, которого мне не хватает?
Чтобы уточнить, я хочу сравнить вышеупомянутый подход с тем, чтобы представление было явно связано с моделью. Например, вы можете передать объект модели транспортного средства в представление, а затем изменить «марку» транспортного средства, сделав это:
vehicle.make = bicycleMakeField.getText();
Это позволит сократить 15 строк кода, которые в настоящее время используются ТОЛЬКО для установки марки автомобиля в одном месте, до одной читаемой строки кода. (И поскольку такого рода операции выполняются сотни раз по всему приложению, я думаю, это было бы большим выигрышем для удобочитаемости и безопасности.)
Обновить
Мы с руководителем группы реструктурировали структуру так, как мы хотели, используя статическую типизацию, сообщили об этом профессору и в итоге дали ему демо. Он достаточно щедр, чтобы позволить нам использовать наш фреймворк до тех пор, пока мы не попросим его о помощи, и если мы сможем поддерживать остальную часть нашей команды в быстром темпе, что кажется нам справедливым.
Ответы:
Подход, предложенный вашим профессором, лучше всего описать как строго типизированный и неправильный почти на каждом уровне.
Сцепление лучше всего уменьшить с помощью инверсии зависимостей , что происходит с помощью полиморфной диспетчеризации, а не с помощью жесткого соединения в ряде случаев.
источник
Ваш профессор делает это неправильно . Он пытается полностью отделить представление и модель, заставляя коммуникацию перемещаться через строку в обоих направлениях (представление не зависит от модели, а модель не зависит от представления) , что полностью противоречит цели объектно-ориентированного проектирования и MVC. Похоже, вместо того, чтобы писать классы и разрабатывать архитектуру на основе ОО, он пишет разрозненные модули, которые просто отвечают на текстовые сообщения.
Чтобы быть несколько честным с профессором, он пытается создать в Java то, что выглядит очень похоже на широко распространенный интерфейс .NET
INotifyPropertyChanged
, который уведомляет подписчиков о событиях изменения посредством передачи строк, которые указывают, какое свойство изменилось. По крайней мере, в .NET этот интерфейс в основном используется для связи из модели данных для просмотра объектов и элементов графического интерфейса (привязка).Если все сделано правильно , такой подход может иметь некоторые преимущества¹:
events
но в Java вам придется создавать классы или объекты и писать код подписки / отписки для каждого события.Итак, вкратце (и для ответа на ваш вопрос), это может быть сделано, но подход, который использует ваш профессор, виноват в том, что он не допускает хотя бы одностороннюю зависимость между представлением и моделью. Это просто не практично, слишком академично и не является хорошим примером того, как использовать инструменты под рукой.
¹ Поиск в Google,
INotifyPropertyChanged
чтобы найти миллион способов, которыми люди пытаются избежать использования магической строки при ее реализации.источник
enum
s (илиpublic static final String
s) следует использовать вместо волшебных строк.Ваш профессор не понимает ОО . Например, имея конкретный класс транспортных средств?
И чтобы этот класс понял марку велосипеда?
Транспортное средство должно быть абстрактным, и должен быть конкретный подкласс под названием Bike. Я бы играл по его правилам, чтобы получить хорошую оценку, а потом забыл его учение.
источник
Я думаю, у вас есть хорошая точка зрения, магические струны плохие. Кто-то из моей команды должен был отладить проблему, вызванную магическими строками пару недель назад (но они написали собственный код, поэтому я держал рот на замке). И это случилось ... в промышленности !
Преимущество его подхода заключается в том, что код может быть быстрее, особенно для небольших демонстрационных проектов. Недостатки в том, что он подвержен опечаткам, и чем чаще используется строка, тем больше шансов, что код опечатки все испортит. И если вы когда-нибудь захотите изменить магическую строку, рефакторинг строк сложнее, чем рефакторинг переменных, поскольку инструменты рефакторинга могут также касаться строк, которые содержат магическую строку (как подстроку), но сами по себе не являются магической строкой, и ее не следует трогать. Кроме того, вам может потребоваться сохранить словарь или индекс магических строк, чтобы новые разработчики не начали изобретать новые магические строки для той же цели и не тратили время на поиск существующих магических строк.
В этом контексте выглядит, что Enum может быть лучше, чем магические строки или даже глобальные строковые константы. Кроме того, интегрированные среды разработки часто предоставляют некоторую помощь при кодировании (автозаполнение, рефакторинг, поиск всех ссылок и т. Д.) При использовании константных строк или перечислений. IDE не окажет особой помощи, если вы используете волшебные строки.
источник
Использование «отраслевого опыта» - плохой аргумент. Ваш профессор должен придумать лучший аргумент, чем этот :-).
Как утверждают другие, использование магических строк, безусловно, осуждается, использование перечислений считается гораздо безопаснее. Перечисление имеет значение и область действия , магические строки - нет. Помимо этого, способ, которым ваш профессор разделяет проблемы, считается более старой и более хрупкой техникой, чем используемая сегодня.
Я вижу, что @backtodos покрывал это, пока я отвечал на это, поэтому я просто добавлю свое мнение о том, что с помощью Inversion of Control (формой которого является Dependency Injection), вы столкнетесь в среде Spring в отрасли очень долго. ..) считается более современным способом борьбы с этим типом развязки.
источник
Давайте будем совершенно ясны; там неизбежно какая-то связь. Тот факт, что существует такая подписываемая тема, является точкой связи, как и характер остальной части сообщения (например, «единственная строка»). Учитывая это, тогда возникает вопрос, является ли связь большей, когда это делается через строки или типы. Ответ на этот вопрос зависит от того, обеспокоены ли вы связью, которая распределена по времени или пространству: будут ли сообщения сохраняться в файле перед последующим чтением или будут отправлены другому процессу (особенно если это не написано на одном языке), использование строк может сделать вещи намного проще. Недостатком является то, что нет проверки типов; грубые ошибки не будут обнаружены до времени выполнения (а иногда даже тогда).
Стратегия смягчения / компрометации для Java может заключаться в использовании типизированного интерфейса, но там, где этот типизированный интерфейс находится в отдельном пакете. Он должен состоять только из Java
interface
и базовых типов значений (например, перечисления, исключения). В этом пакете не должно быть реализаций интерфейсов. Тогда все реализуют это, и, если необходима сложная передача сообщений, конкретная реализация делегата Java может использовать магические строки по мере необходимости. Это также значительно облегчает миграцию кода в более профессиональную среду, такую как JEE или OSGi, и значительно облегчает такие мелочи, как тестирование…источник
Ваш профессор предлагает использовать «магические струны». Хотя он «слабо связывает» классы друг с другом, позволяя вносить более простые изменения, он является анти-паттерном; строки должны очень, ОЧЕНЬ редко использоваться, чтобы содержать или контролировать команды кода, и когда это абсолютно необходимо, значение строк, которые вы используете для управления логикой, должно быть централизованно и постоянно определено, так что есть ОДИН авторитет в отношении ожидаемого значения любая конкретная строка.
Причина очень проста; Строки не проверяются компилятором на синтаксис или согласованность с другими значениями (в лучшем случае они проверяются на правильную форму относительно escape-символов и другого языкового форматирования в строке). Вы можете поместить все, что вы хотите в строку. Таким образом, вы можете получить безнадежно испорченный алгоритм / программу для компиляции, и только когда она запускается, возникает ошибка. Рассмотрим следующий код (C #):
... весь этот код компилируется, сначала попробуйте, но ошибка очевидна при втором взгляде. Существует множество примеров такого рода программирования, и все они подвержены такого рода ошибкам, ДАЖЕ ЕСЛИ вы определяете строки как константы (потому что константы в .NET записываются в манифест каждой библиотеки, в которой они используются, что должно тогда все будет перекомпилировано, когда определенное значение будет изменено, чтобы значение изменилось «глобально»). Так как ошибка не обнаруживается во время компиляции, она должна быть обнаружена во время тестирования во время выполнения, и это гарантируется только при 100% покрытии кода в модульных тестах с адекватным упражнением кода, что обычно встречается только в наиболее абсолютной отказоустойчивости. , системы реального времени.
источник
На самом деле, эти классы все еще тесно связаны. За исключением того, что теперь они тесно связаны таким образом, что компилятор не может сказать вам, когда что-то сломалось!
Если кто-то изменит «BicycleMake» на «BicyclesMake», то никто не узнает, что все сломалось до времени выполнения.
Ошибки во время выполнения обходятся гораздо дороже, чем ошибки во время компиляции - это просто зло.
источник