Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
899
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6087
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4400
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Как найти иголку в стоге сена?
При реализации объектно-ориентированного поиска иголки в стоге сена у вас, по существу, есть три альтернативы:
1. needle.find(haystack)
2. haystack.find(needle)
3. searcher.find(needle, haystack)
Что вы предпочитаете и почему?
Я знаю, что некоторые люди предпочитают второй вариант, потому что он позволяет избежать введения третьего объекта. Однако я не могу избавиться от ощущения, что третий подход более концептуально "correct", по крайней мере, если ваша цель-моделировать "the real world".
В каких случаях, по вашему мнению, целесообразно вводить вспомогательные объекты, такие как поисковик в данном примере, и когда их следует избегать?
Из трех вариантов я предпочитаю вариант #3.
Принцип единой ответственности заставляет меня не ставить поисковые возможности на мои DTOs или модели. Их обязанность - быть данными, а не находить самих себя, и иголки не должны знать о стогах сена, а стога сена не должны знать об иголках.
Как бы то ни было, я думаю, что большинству практикующих OO требуется LONG времени, чтобы понять, почему #3 является лучшим выбором. Я делал OO в течение десяти лет, вероятно, прежде чем я действительно грокнул его.
@wilhelmtell, C++ - это один из очень немногих языков с шаблонной специализацией, которые делают такую систему реально работающей. Для большинства языков общим назначением метода "find" будет идея HORRIBLE.
Как правило, действия должны быть применены к тому, что вы делаете какие-то действия... в данном случае стог сена, поэтому я считаю вариант 2 наиболее подходящим.
У вас также есть четвертая альтернатива, которая, я думаю, будет лучше, чем альтернатива 3:
haystack.find(needle, searcher)
В этом случае он позволяет вам указать способ, которым вы хотите выполнить поиск как часть действия, и таким образом вы можете сохранить действие с объектом, с которым вы работаете.
Существует еще одна альтернатива, которая является подходом, используемым STL из C++:
find(haystack.begin(), haystack.end(), needle)
Я думаю, что это отличный пример того, как C++ кричит от "in your face!" до OOP. Идея заключается в том, что OOP-это не серебряная пуля какого-либо рода; иногда вещи лучше всего описываются в терминах действий, иногда в терминах объектов, иногда ни то, ни другое, а иногда и то, и другое.
Бьярне Страуструп сказал в TC++PL, что при проектировании системы вы должны стремиться отражать реальность в рамках ограничений эффективного и действенного кода. Для меня это означает, что вы никогда не должны слепо следовать за чем-либо. Подумайте о вещах под рукой (стог сена, иголка) и о контексте, в котором мы находимся (поиск, вот о чем это выражение).
Если акцент делается на поиске, то используется алгоритм (действие), который подчеркивает поиск (т. е. гибко вписывается в стога сена, океаны, пустыни, связанные списки). Если акцент делается на стоге сена, инкапсулируйте метод find внутри объекта haystack и так далее.
Тем не менее, иногда вы сомневаетесь и испытываете трудности, делая выбор. В этом случае будьте объектно-ориентированными. Если вы передумаете позже, я думаю, что легче извлечь действие из объекта, чем разделить действие на объекты и классы.
Следуйте этим рекомендациям, и ваш код будет более четким и красивым.
Я бы сказал, что Вариант 1 полностью исключен. Код должен читаться таким образом, чтобы вы знали, что он делает. Вариант 1 заставляет меня думать, что эта игла собирается найти мне стог сена.
Вариант 2 выглядит хорошо, если стог сена предназначен для хранения иголок. ListCollections всегда будет содержать ListItems, поэтому делать collection.find(item) естественно и выразительно.
Я думаю, что введение вспомогательного объекта уместно, когда:
- Вы не контролируете реализацию рассматриваемых объектов
IE: search.find(ObsecureOSObject, файл) - Между этими объектами нет регулярных или осмысленных отношений
IE: nameMatcher.find(2, trees.name)
В этом вопросе я согласен с Брэдом. Чем больше я работаю над чрезвычайно сложными системами, тем больше я вижу необходимость действительно разделять объекты. Он совершенно прав. Очевидно, что иголка ничего не должна знать о стоге сена, так что 1 определенно вышел. Но стог сена не должен ничего знать об иголке.
Если бы я моделировал стог сена, я мог бы реализовать его как коллекцию-но как коллекцию сена или соломы - а не как коллекцию иголок! Однако я бы принял во внимание, что вещи действительно теряются в стоге сена, но я ничего не знаю о том, что именно это за вещи. Я думаю, что лучше не заставлять стог сена искать предметы сам по себе (насколько же умный стог сена в любом случае). Правильный подход ко мне заключается в том, чтобы стог сена представлял собой набор вещей, которые находятся в нем, но не являются соломой или сеном или тем, что придает стогу его сущность.
class Haystack : ISearchableThingsOnAFarm {
ICollection<Hay> myHay;
ICollection<IStuffSmallEnoughToBeLostInAHaystack> stuffLostInMe;
public ICollection<Hay> Hay {
get {
return myHay;
}
}
public ICollection<IStuffSmallEnoughToBeLostInAHayStack> LostAndFound {
get {
return stuffLostInMe;
}
}
}
class Needle : IStuffSmallEnoughToBeLostInAHaystack {
}
class Farmer {
Search(Haystack haystack,
IStuffSmallEnoughToBeLostInAHaystack itemToFind)
}
На самом деле я собирался набирать и абстрагироваться от интерфейсов, а потом понял, насколько я схожу с ума. Я чувствовал себя так, как будто учился в колледже в классе CS... :P
Вы поняли мою идею. Я думаю, что идти как можно более свободно в паре-это хорошо, но, возможно, я немного увлекся! :)
Если и иголка, и стог сена имеют значение DAOs, то варианты 1 и 2 исключаются.
Причина этого заключается в том, что DAOs должен отвечать только за сохранение свойств объектов реального мира, которые они моделируют, и иметь только методы getter и setter (или просто прямой доступ к свойствам). Это делает сериализацию DAOs в файл или создание методов для общего сравнения / общей копии проще писать, так как код не будет содержать целую кучу операторов "if", чтобы пропустить эти вспомогательные методы.
Это просто оставляет вариант 3, который большинство согласится считать правильным поведением.
Вариант 3 имеет несколько преимуществ, причем самым большим преимуществом является модульное тестирование. Это связано с тем, что теперь и иголку, и стог сена можно легко подделать, тогда как при использовании варианта 1 или 2 внутреннее состояние иглы или стога сена должно быть изменено, прежде чем можно будет выполнить поиск.
Во-вторых, теперь, когда поисковик находится в отдельном классе, весь код поиска можно хранить в одном месте, включая общий код поиска. Тогда как если бы код поиска был помещен в DAO, общий код поиска либо хранился бы в сложной иерархии классов, либо в любом случае был бы связан с вспомогательным классом Searcher.
Это всецело зависит от того, что меняется, а что остается неизменным.
Например, я работаю над фреймворком (не OOP), где алгоритм поиска отличается в зависимости от типа иглы и стога сена. Помимо того, что это потребует двойной отправки в объектно-ориентированной среде, это также означает, что не имеет смысла писать ни needle.find(haystack) , ни haystack.find(needle) .
С другой стороны, ваше приложение может с радостью делегировать поиск любому из обоих классов или придерживаться одного алгоритма в целом, и в этом случае решение будет произвольным. В этом случае я бы предпочел путь haystack.find(needle) , потому что кажется более логичным применить находку к стогу сена.
При реализации поиска иголкой а
стог сена в объектно-ориентированном виде,
по сути у вас их три
альтернативы:
needle.find(haystack)
haystack.find(needle)
searcher.find(неедл, стог сена)
Что вы предпочитаете и почему?
При реализации поиска иголкой а стог сена в объектно-ориентированном виде, по сути у вас их три альтернативы:
needle.find(haystack)
haystack.find(needle)
searcher.find(неедл, стог сена)
Что вы предпочитаете и почему?
Поправьте меня, если я ошибаюсь, но во всех трех примерах у вас уже есть ссылка на иглу, которую вы ищете, так что разве это не похоже на поиск ваших очков, когда они сидят на вашем носу? :p
Каламбур в сторону, я думаю, что это действительно зависит от того, что вы считаете ответственностью стога сена в данной области. Разве мы просто заботимся о нем в том смысле, что это вещь, которая содержит иглы (по сути, коллекция)? Тогда haystack.find(needlePredicate) - это нормально. В противном случае, farmBoy.find(predicate, haystack) может быть более подходящим.
Чтобы процитировать великих авторов SICP ,
Программы должны быть написаны для того, чтобы люди их читали, и только случайно для того, чтобы машины их выполняли
Я предпочитаю иметь под рукой оба метода 1 и 2. Используя ruby в качестве примера, он поставляется с .include? , который используется следующим образом
haystack.include? needle
=> returns true if the haystack includes the needle
Хотя иногда, чисто для удобства чтения, я хочу перевернуть его. Ruby не поставляется с методом in? , но это однострочный метод, поэтому я часто делаю это:
needle.in? haystack
=> exactly the same as above
Если это "more important", чтобы подчеркнуть стог сена или операцию поиска, я предпочитаю писать include? .
Часто, однако, ни стог сена, ни поиск - это действительно то, что вас волнует, просто то, что объект присутствует-в этом случае я нахожу in? лучше передает смысл программы.
Это зависит от ваших требований.
Например, если вы не заботитесь о свойствах искателя (например, сила искателя, зрение и т. д.), то я бы сказал haystack.find(needle) было бы самым чистым решением.
Но, если вы действительно заботитесь о свойствах Искателя (или любых других свойствах по этому вопросу), я бы ввел интерфейс ISearcher либо в конструктор haystack, либо в функцию, чтобы облегчить это. Это поддерживает как объектно-ориентированный дизайн (стог сена имеет иглы), так и инверсию инъекции управления / зависимостей (облегчает модульное тестирование функции "find").
Я могу думать о ситуациях, когда любой из первых двух ароматов имеет смысл:
Если игла нуждается в предварительной обработке, как в алгоритме Knuth-Morris-Pratt,
needle.findIn(haystack)(илиpattern.findIn(text))имеет смысл, потому что объект иглы содержит промежуточные таблицы, созданные для эффективной работы алгоритмаЕсли стог сена нуждается в предварительной обработке, как, скажем, в трие, то
haystack.find(needle)(илиwords.hasAWordWithPrefix(prefix)) работает лучше.
В обоих вышеперечисленных случаях один из иголок или стога сена знает о поиске. Кроме того, они оба знают друг о друге. Если вы хотите, чтобы иголка и стог сена не были осведомлены друг о друге или о поиске, searcher.find(needle, haystack) будет уместно.
Ответ на этот вопрос должен фактически зависеть от домена, для которого реализуется решение.
Если вы случайно имитируете физический поиск в физическом стоге сена, у вас могут быть классы
- Космос
- Солома
- Игла
- Самонаводящийся снаряд
Космос
знает, какие объекты находятся в каких координатах
реализует законы природы (преобразует энергию, обнаруживает столкновения и т.д.)
Иголка, Соломинка
расположены в пространстве
реагируйте на силы
Самонаводящийся снаряд
взаимодействует с пространством:
двигает рукой, применяет магнитное поле, сжигает сено, применяет рентгеновские лучи, ищет иглу ...
Thus seeker.find(needle, space) or seeker.find(needle, space, strategy)
Стог сена просто случайно оказывается в том месте, где вы ищете иголку. Когда вы абстрагируете пространство как своего рода виртуальную машину (подумайте о матрице), вы можете получить все это с помощью haystack вместо пространства (решение 3/3b) :
seeker.find(needle, haystack) or seeker.find(needle, haystack, strategy)
Но матрица была доменом, который должен был быть заменен только стогом сена, если ваша игла не могла быть где-то еще.
И опять же, это была просто анология. Интересно что это открывает разум для совершенно новых направлений:
1. Почему вы вообще потеряли иглу? Можете ли вы изменить процесс,чтобы не потерять его?
2. Вам нужно найти потерянную иглу или вы можете просто взять другую и забыть о первой? (Тогда было бы неплохо, если бы игла растворилась через некоторое время)
3. Если вы регулярно теряете свои иглы и вам нужно найти их снова тогда вы можете захотеть
сделайте иглы, которые способны найти себя, например, они регулярно спрашивают себя: я потерялся? Если ответ утвердительный, они посылают кому-то свою рассчитанную позицию GPS или начинают пищать или что-то еще:
needle.find(space)илиneedle.find(haystack)(Решение 1 )установите стог сена с камерой на каждой соломинке, после чего вы можете спросить у стога сена hive ума, видел ли он иголку в последнее время:
haystack.find(needle) (решение 2 )прикрепите бирки RFID к вашим иглам, поэтому вы можете легко триангулировать их
Это все только для того, чтобы сказать, что в вашей реализации вы сделали иголку и стог сена и большую часть времени матрицу на каком-то уровне.
Так что решайте в соответствии с вашим доменом:
- Разве стог сена предназначен для того, чтобы содержать иголки? Затем перейдите к решению 2.
- Разве это естественно, что игла теряется где попало? Затем перейдите к решению 1.
- Может быть, иголка случайно потерялась в стоге сена? Затем перейдите к решению 3. (или рассмотрим другую стратегию восстановления)
haystack.find(needle), но там должно быть поле поиска.
Я знаю, что инъекция зависимости-это все модно, поэтому меня не удивляет, что @Mike Stone's haystack.find(needle, searcher) был принят. Но я не согласен: выбор того, какой поисковик используется, кажется мне решением для стога сена.
Рассмотрим два ISearchers: MagneticSearcher итерации по объему, перемещая и шагая Магнит таким образом, чтобы он соответствовал силе Магнита. QuickSortSearcher делит стопку на две части до тех пор, пока игла не будет видна в одном из подпространств. Правильный выбор искателя может зависеть от того, насколько велик стог сена (например, относительно магнитного поля), как игла попала в стог сена (т. е. действительно ли положение иглы случайное или оно смещено?), прием.
Если у вас есть haystack.find(needle, searcher), вы говорите: "выбор наилучшей стратегии поиска лучше всего делать вне контекста стога сена."Я не думаю, что это скорее всего будут исправлять. Я думаю, что более вероятно, что "haystacks know how best to search themselves." добавляет setter, и вы все еще можете вручную ввести поисковик, если вам нужно переопределить или для тестирования.
Брэд Уилсон указывает, что объекты должны нести единую ответственность. В крайнем случае, объект несет одну ответственность и не имеет никакого государства. Тогда он может стать таким... функция.
needle = findNeedleIn(haystack);
Или вы могли бы написать это так:
SynchronizedHaystackSearcherProxyFactory proxyFactory =
SynchronizedHaystackSearcherProxyFactory.getInstance();
StrategyBasedHaystackSearcher searcher =
new BasicStrategyBasedHaystackSearcher(
NeedleSeekingStrategies.getMethodicalInstance());
SynchronizedHaystackSearcherProxy proxy =
proxyFactory.createSynchronizedHaystackSearcherProxy(searcher);
SearchableHaystackAdapter searchableHaystack =
new SearchableHaystackAdapter(haystack);
FindableSearchResultObject foundObject = null;
while (!HaystackSearcherUtil.isNeedleObject(foundObject)) {
try {
foundObject = proxy.find(searchableHaystack);
} catch (GruesomeInjuryException exc) {
returnPitchforkToShed(); // sigh, i hate it when this happens
HaystackSearcherUtil.cleanUp(hay); // XXX fixme not really thread-safe,
// but we can't just leave this mess
HaystackSearcherUtil.cleanup(exc.getGruesomeMess()); // bug 510000884
throw exc; // caller will catch this and get us to a hospital,
// if it's not already too late
}
}
return (Needle) BarnyardObjectProtocolUtil.createSynchronizedFindableSearchResultObjectProxyAdapterUnwrapperForToolInterfaceName(SimpleToolInterfaces.NEEDLE_INTERFACE_NAME).adapt(foundObject.getAdaptable());
У вас также есть четвертая альтернатива, которая, я думаю, будет лучше, чем альтернатива 3:
haystack.find(needle, searcher)
У вас также есть четвертая альтернатива, которая, я думаю, будет лучше, чем альтернатива 3:
haystack.find(needle, searcher)
Я понимаю вашу точку зрения, но что, если searcher реализует интерфейс поиска, который позволяет искать другие типы объектов, чем стога сена, и находить в них другие вещи, чем иглы?
Интерфейс также может быть реализован с помощью различных алгоритмов, например:
binary_searcher.find(needle, haystack)
vision_searcher.find(pitchfork, haystack)
brute_force_searcher.find(money, wallet)
Но, как уже отмечали другие, я также думаю, что это полезно только в том случае, если у вас действительно есть несколько алгоритмов поиска или несколько доступных для поиска или находимых классов. Если нет, то я согласен, что haystack.find(needle) лучше из-за его простоты, поэтому я готов пожертвовать некоторым "correctness" для него.
Стог сена не должен знать об игле, а игла не должна знать о стоге сена. Искатель должен знать и о том, и о другом, но должен ли стог сена знать, как искать самого себя, - это реальная точка соприкосновения.
Поэтому я бы выбрал сочетание 2 и 3; стог сена должен быть в состоянии сказать кому-то еще, как его искать, и искатель должен быть в состоянии использовать эту информацию для поиска стога сена.
Смесь 2 и 3, На самом деле.
Некоторые стога сена не имеют специальной стратегии поиска; примером этого является массив. Единственный способ найти что-то-начать с самого начала и проверить каждый элемент, пока не найдете тот, который вы хотите.
Для такого рода вещей, вероятно, лучше всего использовать свободную функцию (например, C++).
Некоторые стога сена могут иметь специализированную стратегию поиска, наложенную на них. Массив может быть отсортирован, что позволяет использовать двоичный поиск, например. Свободная функция (или пара свободных функций, например сортировка и binary_search), вероятно, является лучшим вариантом.
Некоторые стога сена имеют интегрированную стратегию поиска как часть их реализации; ассоциативные контейнеры (хэшированные или упорядоченные наборы и карты) все это делают, например. В этом случае поиск, вероятно, является существенным методом поиска, поэтому он, вероятно, должен быть методом, т. е. haystack.find(needle).
Пытается ли код найти конкретную иглу или просто любую иглу? Это звучит как глупый вопрос, но он меняет проблему.
Искать конкретную иглу кода в вопросе имеет смысл. Искать любую иголку было бы больше похоже
needle = haystack.findNeedle()
или
needle = searcher.findNeedle(haystack)
В любом случае, я предпочитаю иметь искателя этого класса. Стог сена не знает, как искать. С точки зрения CS это просто хранилище данных с LOTS дерьма, которое вам не нужно.
стог сена может содержать различные вещества одним из видов материала является игла finder-это то, что отвечает за поиск вещей искатель может принять кучу вещей как источник того, где найти вещь искатель также может принять описание материала вещи, которую ему нужно найти
поэтому, предпочтительно, для гибкого решения вы бы сделали что-то вроде: Интерфейс IStuff
Стог сена = IList<IStuff> Игла : IStuff
Искатель .Найти(IStuff stuffToLookFor, IList<IStuff> stuffsToLookIn)
В этом случае ваше решение не будет привязано только к иголке и стогу сена, но оно может быть использовано для любого типа, реализующего интерфейс
так что если вы хотите найти рыбу в океане, вы можете.
var results = Finder.Find(fish, океан)
Если у вас есть ссылка на объект иглы, зачем вы его ищете? :) Проблемная область и примеры использования говорят вам, что вам не нужно точное положение иглы в стоге сена (например, что вы могли бы получить от list.indexOf(element)), вам просто нужна игла. А у тебя его еще нет. Так что мой ответ примерно такой
Needle needle = (Needle)haystack.searchByName("needle");
или
Needle needle = (Needle)haystack.searchWithFilter(new Filter(){
public boolean isWhatYouNeed(Object obj)
{
return obj instanceof Needle;
}
});
или
Needle needle = (Needle)haystack.searchByPattern(Size.SMALL,
Sharpness.SHARP,
Material.METAL);
Я согласен, что есть больше возможных решений, которые основаны на различных стратегиях поиска, поэтому они вводят searcher. Было много комментариев по этому поводу, поэтому я не обращаю на это внимания здесь. Я хочу сказать, что решения выше забывают о прецедентах-какой смысл искать что-то, если у вас уже есть ссылка на это? В самом естественном случае использования у вас еще нет иглы, поэтому вы не используете переменную иглу.