Как вы находите иголку в стоге сена? - PullRequest
72 голосов
/ 23 августа 2008

При реализации поиска иголки в стоге сена объектно-ориентированным способом у вас есть три варианта:

1. needle.find(haystack)

2. haystack.find(needle)

3. searcher.find(needle, haystack)

Что вы предпочитаете и почему?

Я знаю, что некоторые люди предпочитают второй вариант, потому что он избегает введения третьего объекта. Однако я не могу не чувствовать, что третий подход является более концептуально «правильным», по крайней мере, если ваша цель состоит в моделировании «реального мира».

Как вы думаете, в каких случаях оправданно вводить вспомогательные объекты, такие как искатель в этом примере, и когда их следует избегать?

Ответы [ 29 ]

1 голос
/ 05 ноября 2008

Если у вас есть ссылка на игольный объект, почему вы ищете его? :) Проблемная область и варианты использования говорят вам, что вам не нужно точное положение иглы в стоге сена (например, что вы можете получить из 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);

Я согласен, что существует больше возможных решений, основанных на разных стратегиях поиска, поэтому они вводят поисковик. Было достаточно комментариев по этому поводу, поэтому я не обращаю на это внимания. Суть в том, что решения выше забывают о сценариях использования - какой смысл искать что-то, если у вас уже есть ссылка на это? В наиболее естественном случае у вас еще нет иглы, поэтому вы не используете переменную иглу.

1 голос
/ 24 августа 2008

У вас также есть четвертый вариант, который, я думаю, будет лучше, чем вариант 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) лучше из-за его простоты, поэтому я готов пожертвовать некоторой «правильностью» для этого.

1 голос
/ 23 августа 2008

@ Питер Мейер

Вы поняли идею. Я думаю, что работать как можно слабее, это хорошая вещь, но, возможно, я немного увлекся! :)

Э-э-э ... да ... Я думаю, что IStuffSmallEnoughToBeLostInAHaystack это красный флаг: -)

1 голос
/ 28 августа 2008

Хейстек не должен знать об иголке, а иголка не должна знать о стоге сена. Поисковику нужно знать и то, и другое, но реальный смысл спора - в том, должен ли стог сена знать, как искать себя.

Так что я бы пошел со смесью 2 и 3; стог сена должен быть в состоянии сказать кому-то еще, как его искать, и искатель должен иметь возможность использовать эту информацию для поиска в стоге сена.

1 голос
/ 20 ноября 2009

Брэд Уилсон указывает на то, что объекты должны нести единоличную ответственность. В крайнем случае, объект имеет одну ответственность и не имеет государства. Тогда это может стать ... функцией.

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());
0 голосов
/ 05 января 2018

В большинстве случаев я предпочитаю иметь возможность выполнять простые вспомогательные операции, подобные этим, для основного объекта, но в зависимости от языка у рассматриваемого объекта может не быть достаточного или разумного доступного метода.

Даже в таких языках, как JavaScript ), которые позволяют расширять / расширять встроенные объекты, я считаю, что это может быть как удобно, так и проблематично (например, если будущая версия языка вводит более эффективный метод который переопределяется пользовательским).

Эта статья хорошо описывает такие сценарии.

0 голосов
/ 13 августа 2012
haystack.iterator.findFirst(/* pass here a predicate returning
                               true if its argument is a needle that we want */)

iterator может быть интерфейсом к любой неизменной коллекции, при этом коллекции имеют общий метод findFirst(fun: T => Boolean), выполняющий эту работу. Пока стог сена является неизменным, нет необходимости скрывать какие-либо полезные данные "извне". И, конечно, нехорошо связывать воедино реализацию нестандартной коллекции и некоторые другие вещи, которые имеют haystack. Разделяй и властвуй, хорошо?

0 голосов
/ 13 ноября 2008

Другим возможным способом может быть создание двух интерфейсов для объекта поиска, например, стог сена и объект ToBeSearched, например, игла. Итак, это можно сделать следующим образом

public Interface IToBeSearched
{}

public Interface ISearchable
{

    public void Find(IToBeSearched a);

}

Class Needle Implements IToBeSearched
{}

Class Haystack Implements ISearchable
{

    public void Find(IToBeSearched needle)

   {

   //Here goes the original coding of find function

   }

}
0 голосов
/ 13 ноября 2008

Определенно третий, ИМХО.

Вопрос об иголке в стоге сена является примером попытки найти один объект в большом наборе других, что указывает на то, что ему потребуется сложный алгоритм поиска (возможно, с использованием магнитов или (более вероятно) дочерних процессов) и не имеет смысла ожидать от стога сена управления потоками или осуществления сложного поиска.

Однако объект поиска предназначен для поиска, и можно ожидать, что он будет знать, как управлять дочерними потоками для быстрого двоичного поиска, или использовать свойства искомого элемента для сужения области (т. Е. Магнит для поиска черные металлы).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...