1. C# / Говнокод #11252

    +138

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    public class ImageWorkerSingleton
    {
    	private static ImageWorkerSingleton instance;
    
    	private ImageWorkerSingleton() { }
    
    	public static ImageWorkerSingleton Instance
    	{
    		get
    		{
    			if (instance == null)
    			{
    				instance = new ImageWorkerSingleton();
    			}
    			return instance;
    		}
    	}
    
    	public void Init() {}
    
    	public string UrlToImage(Guid id, ImageTypeEnum imageType = ImageTypeEnum.PhotoUndefined)
    	{
    		...
    	}
    
    	public bool IsImageExist(Guid id, ImageTypeEnum imageType = ImageTypeEnum.PhotoUndefined)
    	{
    		...
    	}
    }

    И на кой, здесь синглтон о_О

    Запостил: DarkThinker, 20 Июня 2012

    Комментарии (34) RSS

    • > И на кой, здесь синглтон о_О
      Статические методы автора уже не возбуждали...
      Ответить
      • ))) видимо
        Ответить
      • Статические методы нужны очень редко. Не зная задачи, могу предложить такой вариант:
        public class ImagePath {
        
          public ImagePath(Guid id, ImageType imageType) { /* ... */ }
        
          public string URL { get { /* ... */ } }
        
          public bool Exists { get { /* ... */ } }
        }
        Ответить
        • >Статические методы нужны очень редко
          отнюдь. они дешевле
          Ответить
          • А если пакетик из-под чая не выбрасывать, а использовать несколько раз, можно накопить на квартиру за два месяца.

            Ты хоть понимаешь, что если файл с изображением лежит на диске, то один вызов Exists будет стоить в сотни раз дороже, чем конструирование объекта ImagePath?
            Я не говорю, что статические методы не нужны. Они нужны редко, например, для фабричных методов (в Java это даже помогает унылому выводу типов-параметров обобщённых классов), для оформления утилитных функций в идиотской модели "всё лежит внутри класса", принятой в Java и C#, ведь гораздо более естественной формой для вещей вроде StringUtils является не класс со статическими методами, а пакет/пространство имен/модуль с набором обыкновенных функций.

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

            Удивляюсь до чего разумные люди работали над Scala: выкинули статику нахрен и сделали всё по человечески.
            Ответить
            • Ну, вроде как, этот случай и относится к утилитным функциям? Как стандартные Path и File.
              Стоит ли вместо
              if (ImagePath.Exists(guid))
                url = ImagePath.URL(guid);

              писать
              if (new ImagePath(guid).Exists)
                url = new ImagePath(guid).URL;

              или
              ImagePath path = new ImagePath(guid);
              if (path.Exists)
                url = path.URL;

              ? Хотя, конечно, объект ImagePath можно хранить и передавать в качестве аргументов.
              Ответить
              • > объект ImagePath можно хранить и передавать в качестве аргументов
                Да, он нужен именно для того, чтобы не таскать одну и ту же пачку параметров в сигнатурах методов.
                Я не особо пишу на c#, в Java, например, для работы с File (на самом деле там это Path) нужно создавать объект, и у него есть метод exists. Когда параметров мало и они примитивны (у обычного Path это одна строка), разницы нет. Когда параметров становится больше и они могут меняться со временем, объектный подход получает преимущества в удобстве работы и сопровождения.
                Ответить
                • В шарпе в общем-то аналогично: можно использовать класс File с набором статических методов, а можно создать объект класса FileInfo.
                  Согласен, что в разных случаях удобней разные подходы.
                  Ответить
            • >Ты хоть понимаешь, что если файл с изображением лежит на диске, то один вызов Exists будет стоить в сотни раз дороже, чем конструирование объекта ImagePath?
              Не надо тут переиначивать. Причём тут конкретная задача ImagePath? Тебе говорят, о том что в целом статика дешевле - это аргумент.
              Конкретно пример - new Integer(a) и Integer.valueOf(a).

              От статических методов есть несомененная польза. По-прежнему есть люди, которые пишут структурно, не сильно заморачиваясь ООП, особенно там где оно нахер не нужно.

              На мой вкус equals(a,b) выглядит красивей чем a.equals(b) и позволит избежать boilerpalte проверок чтоб не получить NPE.

              P.S. Редчайший случай, когда я с тобой не согласен, и полностью разделяю мнение оппонента.
              Ответить
              • > Конкретно пример - new Integer(a) и Integer.valueOf(a)
                Это фабричный метод, я их очень люблю, и об этом и написал.

                > equals(a,b) выглядит красивей чем a.equals(b)
                equal(a,b) можно убрать из объекта и сделать полиморфным только в том случае, если в языке есть мультиметоды, которых ни в java, ни в c# не наблюдается. От a.equals(b) никуда не денешься. Проблема с NPE - epic fail разработчиков Java. В Scala, к примеру, оператор == работает как правильный equal(a, b), для сравнения адресов используется eq. К тому же, это как раз относится ко второму случаю (с библиотеками простых функций), когда статики нужны в наших кривоватых ЯП.
                Ответить
                • >Проблема с NPE - epic fail разработчиков Java.
                  Мы сейчас говорим о Java/C#. И в этих языках статик-методы (extension-методы) позволяют избежать многих подобных проблем.

                  >Это фабричный метод, я их очень люблю, и об этом и написал.
                  Я внимательно прочитал то что написал

                  >помогает унылому выводу типов-параметров
                  Речь шла о удобстве женериков в методах (хитрый автовывод, которого нет в конструкторах) и ограничениях на то что вызов super - всегда первый.
                  А я и abatishchev говорим о том что статика позволяет не плодить ненужных, лишних объектов для выполнения простых действий: юзать старые или выполнять действия над существующими.

                  >А если пакетик из-под чая не выбрасывать, а использовать несколько раз
                  Это как раз пример с Integer и кешем.
                  Ответить
                  • > статика позволяет не плодить ненужных, лишних объектов
                    Если у нам нужно сделать, к примеру, сервис синглтоном (т.е. нам нужен только один объект), это не значит, что нужно делать его методы статическими. Достаточно дать хинт DI фрэймворку, чтобы он создавал ровно один объект и использовал его повторно.

                    По поводу Integer и кэша - никто не запрещает сделать у ImagePath фабричный метод и кэшировать часто используемые пути (или правильней - спрятать кэш в вызов сервиса c GetPath). Это вещь, перпендикулярная полиморфности/статичности Exists и URL.
                    Ответить
                    • >дать хинт DI фрэймворку, чтобы он создавал ровно один объект и использовал его повторно
                      Я понял к чему ты клонишь. Статик-методы не нужны редко - юзайте di-фреймворки.

                      >никто не запрещает сделать у ImagePath фабричный метод
                      И он ессно будет статическим.
                      >спрятать кэш в вызов сервиса c GetPath
                      А вот этого не хотет.

                      Этого будет достаточно
                      public static ImagePath on(Guid id, ImageType imageType);
                      вызывать так
                      ImagePath.on(guid,type).setUrl(url)

                      Хотя вопрос конечно спорный и всё зависит от конкретной ситуации.
                      Ответить
                      • > И он ессно будет статическим.
                        Повторюсь, статика предпочтительна для
                        1. Фабричных методов
                        2. Утилитных функций, не вписывающихся в ООП (new StringUtils().join() o_O)

                        > А вот этого не хотет.
                        Чем мне не нравится кэш ImagePath в самом ImagePath - пути к каталогам нужно конфигурить, а схемы сохранения могут быть сложными, потому впихивать разборы конфигураций и общение хрен знает с чем в простые DTOшки как-то некошерно.
                        Ответить
                  • И да, я не спорю, что статики иногда нужны для повышения производительности. Если бы я писал для Java ME, или если бы нужно было работать с миллионом ImagePath (наверняка это не тот случай) сразу, я бы постарался избежать создания ненужных объектов везде, где только можно.
                    Но это - исключительные ситуации, которые встречаются нынче нечасто.
                    Просто пытаюсь донести своё мнение, полученное из (горького?) опыта: не нужно использовать статику только потому, что она чуть шустрее, там, где это не имеет никакого значения.
                    Ответить
                  • > А я и abatishchev говорим о том что статика позволяет не плодить ненужных, лишних объектов
                    Вообще-то, я считал, что abatishchev имеет ввиду немного другое - что вызов статического метода в VM происходит быстрее, чем вызов полиморфного (само собой, это так), т.е. invokestatic vs invokevirtual
                    Ответить
              • Объясню мою нелюбовь к статикам на примере. У нас в проекте есть сервис, который возвращает текущего пользователя, пусть CurrentUserService. Чтобы не инжектить его (это ведь так сложно), умницы или умники написали статический CurrentUserUtil.currentUser(), который лезет в спринговый контекст, выцепляет оттуда бин сервиса по имени и вызывает у него соответствующий метод. Гораздо удобней, чем инжекция, не так ведь?

                И вот теперь самое интересное: давайте ка попробуем потестить модуль, использующий услуги по получению текущего пользователя. Если с инжекцией всё просто - подкинь стаб и готово - то со статиками нужно использовать чёрную магию PowerMock или честно поднимать спринговый контекст и класть туда стаб.
                Ответить
                • А ну так это просто ваши IoC и DI - некошерная вещь, почему-то нынче шибко популярная.
                  А я это дело недолюбливаю.
                  >Гораздо удобней, чем инжекция, не так ведь?
                  Именно по этой причине.

                  >который лезет в спринговый контекст, выцепляет оттуда бин сервиса по имени
                  Тут проблема другая - намешали 2 парадигмы.
                  Если в проекте используется DI - все должны инжектить, если оперирование через статик-методы, то никто не должен пытаться внедрить IoC.

                  В проекте должны быть единый подход, единый стиль кодинга, единое соглашение по неймингу переменных. Причем похуй кому что не нравится - соблюдать должны все.
                  Ответить
                  • Ну пусть у нас всё через статики и CurrentUserUtils.currentUser() лезет в сессию, а не в спринг. Тестировать зависимые модули один хрен значительно сложнее, ибо coupling.
                    Ответить
                    • Это еще непонятно что сложнее - наплодить всяких интерфейсов, бинов и прочего di-ного оверхеда в котором зачастую без поллитры не разобраться или тестировать "зависимую" статику.
                      Ответить
                      • Зависит от размера проекта и количества усилий, которое вы готовы затратить на тестирование. Не существует абсолютных истин, есть только относительные.
                        Ответить
                        • оба подхода хороши, и не всегда сразу очевидно, какой лучше. иногда нужно попробовать оба.
                          чаще статика полезна для классов утилит, фабрик, синглтонов. вот только не надо скатываться в процедурщину.
                          динамика лучше, когда есть некий контекст (кстати, фабричный метод и тут годится), и всякого рода builder'ов типа guava.
                          Ответить
        • Более правильным путём, конечно, будет реализация сервиса, который плодит эти ImagePath'ы (ну не лезть же им на диск самим). Получается что-то вроде этого:
          public interface IImageService {
            public ImagePath GetPath(Guid id, ImageType imageType);
            /* ... */
          }
          public class ImagePath {
            public Guid Id { get { /* ... */ } }
            public ImageType Type { get { /* ... */ } }
            public string URL { get { /* ... */ } }
            public bool Exists { get { /* ... */ } }
          }
          Ответить
    • интересная 19 строка
      Ответить
      • И в документации написать: You must call Init() once per thread. Пусть задолбаются.
        Ответить
        • Да. С синглтоном это особенно гармонирует.
          Ответить
    • показать все, что скрытоКГ/АМ! (спойлер: ОП - ХУЙ!)
      Ответить

    Добавить комментарий