Как известно, програмист, он никакой не програмист пока не освоил ООП.
И как известно, ООП никак не освоенно програмистом, пока он слету не перечислил все ООП паттерны с примерами из жизни... так как именно эти потерны и раскрывают потенциал ООП.
Но в Апекс у нас обычно нет такой глубины задач, чтобы внедрять паттерны, да и об ООП в целом не каждый день вспоминаешь. (но конечно у нас есть свои паттерны, связанные с лимитами и\или организацией работы тригера).
так вот, предлагаю в этой теме немного вспомнить об ООП паттернах. Где-то на форуме уже приводилась ссылка на статью об ООП паттернах в СФ.
пока такие вопросы: изучаю Factory Pattern вот здесь:
так вот там пример фабрики у которой НЕТ захардкоденных селекторов того какой продукт изготовить, а все варианты продуктов с АйДи прописываются в HashMap и оттуда берутся. так вот меня удивило то, что класс там упоминается просто как класс, то есть вроде MyClass.class и потом из такого упоминанию создается экземпляр (!):
class ProductFactory { private HashMap m_RegisteredProducts = new HashMap();
public void registerProduct (String productID, Class productClass) { m_RegisteredProducts.put(productID, productClass); }
Я учу ООП паттерны по выходным, так что вопросы на эту тему у меня будут возникать с перерывами. И не знаю, насколько я могу использовать вашу доброту, но чувствую что вы и сами не против поговорить на эту тему.
в чем экзистенциальный смысл такого класса-фабрики?
как я понял, этот клас по свому сущетсву является больщим switch-ом (при этом это может быть решено по нубски - просто захрадкодить услные операторы в фабрику, или сделать более хитро, короче и главное гибчее - как описано выше). Т.е. одна строка фабрики замещает в конечном коде много строк. (ну и возвращает фабрика конечно какой то обобщенный через Интерфейс или суперклассный тип, которые являются абстрактным слоем между модулями, хотя это - побочный положительный эффект, а смысл Фабрики именно в сокращении строк кода, я так понял).
в чем экзистенциальный смысл такого класса-фабрики?
Создание нужного тебе объекта.
смысл Фабрики именно в сокращении строк кода, я так понял
Ну вообще смысл большинства шаблонов - уменьшение дублированного кода. Например, тебе нужно создать сложный объект и недостаточно просто вызвать конструктор и ты пишешь класс-фабрику для создания этого объекта, а если в будущем логика создания изменится тебе не придется бегать по всем проекту и исправлять код, ты все сможешь сделать в одном месте. Также фабрика применима для создания потомков одного базового типа.
спасибо, а что в книге: общее архитектурное и БА обсуждение построения приложений или примеры кода, паттернов, DB схем? потому что есть книги Jonathan Sapir - там общая часть, а есть книга Dan Appleman "Advanced APEX" - там конкреные ситуации с кодом. И нет ничего между этими двумя вариантами.
спасибо, а что в книге: общее архитектурное и БА обсуждение построения приложений или примеры кода, паттернов, DB схем? потому что есть книги Jonathan Sapir - там общая часть, а есть книга Dan Appleman "Advanced APEX" - там конкреные ситуации с кодом. И нет ничего между этими двумя вариантами.
Ну вот это вполне между ними: и обсуждение шаблонов проектирования (применительно к Force.com) и код, собственно вся книга - это проетирование/разработка примера-приложения на Force.com c учетом шаблонов.
Просто большиство людей, пишущих код, очень ленивые и совершенно не думают о гибкости кода, расширяемости и дельнейшей поддержке.
Эх, Gres, Gres, проблема не только в нас, криворуких, дело в том что часто менеджеры
совершенно не думают о гибкости кода, расширяемости и дальнейшей поддержке
все что мы слышим: давай, давай как есть двигай в прод, что ты там выдумываешь, кто там разберет твои премудрости после тебя...
но я на выходных напишу фабрику с именами классов для себя, дайте только идею в каком случае, сценарии ее можно использовать (простейшие варианты, плиз, но жизненные)
что ты там выдумываешь, кто там разберет твои премудрости после тебя...
Золотые слова :D
По опыту знаю здесь проблема не в том что там кто чего то выдумывает, а вообщей подготовке спеца который потом будет разбираться время тратить,пример работал в одно конторе там реально было два умных тeam lead, cчас уже архитекторы,Там шаблоны двигали сверху а не снизу,я сказал что все так пишем значит все пишем,заказчик подождет все решение проблемы.В наших реалях хотя бы ТDD освоили.
Согласен, все идет сверху. Абсолютно верно. Подстроиться под стиль программирования не так сложно. Пару раз железной линейкой по пальцам получить и все будет нормально.
Я помню как-то на собеседовании мне задали очень интересный вопрос: "Если вы видите что решение вашего лида неверное (плохое), то что вы будете делать?" Я ответил что "Конечно обсужу, предложу свою точку зрение, но если лид настаивает на своем решении, буду делать как лид сказал". Несостоявшиеся Директор и Лид заулыбались. Не знаю хорошо я ответил или нет Просто у меня за плечами дохрена лет армии и я знаю что такое субординация и что значит обсуждать приказы старших. Кстати как этого не хватает в IT фирмах.
Это я к тому что все зависит от Главного. Хочет Главный чтобы был ООП, будет ООП. Хочет чтобы было по-быстрому, будет по-быстрому Я думаю то что TDD не освоили это не проблема того что "не освоили", а проблема того что "не используют".
Кстати, осилил приведенную выше книженцию по "Force.com Enterprise Architecture". На примерах в книге довольно легко понять чего стоят в апексе самые фундаментальные паттерны, но нужно учитывать, что все там строится на использовании опенсоурсного фреймворка Financial Force.
Просмотрев все предлагаемые решения, не могу сказать что готов все это взять себе на вооружение в проект, особенно реализацию отдельной прослойки селекторов (используемые критерии фильтрации достаточно уникальны) и подхода к передаче айдишников вместо конкретных экземпляров sObject (повторные селекты по таблицам с 1кк+ записей для синхронных операций сильно влияют на быстродействие).
В некоторых небольших проектах на десяток пользователей (без видимой перспективы к росту инстанса) я бы даже не стал заморачиваться с разворачиванием доменной модели и прослойки сервисов, ибо это может неоправданно увеличить порог входа для новых разработчиков и увеличить затраты на имплементацию простейших функций.
проблема не только в нас, криворуких, дело в том что часто менеджеры
Менеджеры есть у всех, дело в идеологии и привычке. Ты пишешь код так, как ты привык его писать, и если у тебя нет желания менять стиль/развиваться, то все останется на своих местах.
Просмотрев все предлагаемые решения, не могу сказать что готов все это взять себе на вооружение в проект, особенно реализацию отдельной прослойки селекторов (используемые критерии фильтрации достаточно уникальны) и подхода к передаче айдишников вместо конкретных экземпляров sObject (повторные селекты по таблицам с 1кк+ записей для синхронных операций сильно влияют на быстродействие).
Ну как бы это же не серебрянная пуля, а просто еще один подход у проектированию. Я бы тоже весь их framework в проект не потащил.
В некоторых небольших проектах на десяток пользователей (без видимой перспективы к росту инстанса) я бы даже не стал заморачиваться с разворачиванием доменной модели и прослойки сервисов, ибо это может неоправданно увеличить порог входа для новых разработчиков и увеличить затраты на имплементацию простейших функций.
вот именно такие мои проекты, хорошо описано.
но все равно буду шевелится сам и изучать новые вещи, даже если меня и не шевелят.
но все равно буду шевелится сам и изучать новые вещи, даже если меня и не шевелят.
Я бы лучше направил твою энергию на изучения различных интеграций, чем тратил время на вопросы как усложнить себе жизнь. Займись плотно изучением темы создания на базе Salesforce call center. Полностью, весь процесс с нуля. Развертывание call center (различных типовых решений) интеграция с Salesforce и не просто интеграция на уровне стандартных настроек, а CTI, WebRTC. Знаю, тема сложная, но результат ее освоения будет ОГРОМНЫЙ. Вот это нужно сегодня 99% бизнеса, а не сколько паттернов проектирования ты знаешь.
Пусть где-то будет говнокод (но Salesforce уже своего рода фреймворк, который диктует правила структурирования кода, так что это уже не говнокод). Зато если твои решения будут заставлять заказчиков писаться от радости, вот это будет настоящее признание твоей работы.
но все равно буду шевелится сам и изучать новые вещи, даже если меня и не шевелят.
Я бы лучше направил твою энергию на изучения различных интеграций, чем тратил время на вопросы как усложнить себе жизнь.
Конечно, просто необходимо шевелиться. С Дмитрием я совершенно не согласен. Технологии меняются, приходят новые, а базовые принципы программирования и культура написания кода остаются постоянными.
С Дмитрием я совершенно не согласен. Технологии меняются, приходят новые, а базовые принципы программирования и культура написания кода остаются постоянными.
Вот тут есть одна загвоздка. Принципов проектирования куча и все хороши. И получается что знать и использовать весь этот зоопарк очень сложно и не каждому хочется. Поэтому обычно программист выбирает что-то одно, вырабатывает свой любимый алгоритм проектирования и работает (продвигает) его. И что получится если встретятся два таких программиста, которые используют разные техники - ничего хорошего не будет. А так и получается. Поэтому считаю что нужно по максимуму использовать стандартный функционал фреймворков (того же Salesforce) и не городить огород. Все равно придет другой программист и все сломает. Это не только мои наблюдений, уже сотню раз встречал замечательную мысль "используйте принципы проектирования в своих личных проектах, а чужих проектам (заказчиков) делайте проще."
Типичный пример - недавно был у нас на проекте один товарищ (не долго) (кстати говорил что на этом форуме сидят одни школьники, поэтому тут делать нечего) дали ему сделать интеграцию с веб сервисом внешним. Он сделал - создавал несколько классов, с кучей методов которые которые дергают друг друга по цепочке отдельно для модели данных, для создания запросов, для обработки запросов, для того чтобы заставить все это работать вместе. Не спорю, это делалось по каким-то принципам и наверное должно быть круто спроектировано. Но вот товарищ ушел и кто будет во всем этом разбираться и поддерживать? И нафига такие сложности? Мне проще и думаю другим после меня будет проще сделать 1 класс с 1 методом для того чтобы дернуть веб сервис, получить данные, распарсить и сложить в базу. ВСЕ! Да, пусть таким методов будет несколько, под каждый запрос, зато все предельно просто и понятно. И не надо говорить что это говнокод. Говнокод получается когда на проект приходят несколько умных людей. И хорошо, если они друг друга понимают или один уступает другому иначе случается жо....
Он сделал - создавал несколько классов, с кучей методов которые которые дергают друг друга по цепочке отдельно для модели данных, для создания запросов, для обработки запросов, для того чтобы заставить все это работать вместе. Не спорю, это делалось по каким-то принципам и наверное должно быть круто спроектировано
не будем ругаться, лучше внимательнейше разберем как это было сделано. собственно все эти замороки преследовали одну цель - сделать код более гибким к расширению и дополнению. (понятно что в некоторых случаев это не нужно, или кажется что это не нужно).
Дмитрий, не сочти за труд, пожалуйста, создай тему "В поиске правильной модели WS клиента" в разделе Интеграция (этот вопрос явно заслуживатеся отдельной темы), и опиши в качестве исходного примера работу этого сервис-клиента (словами или UML схемой).
Дмитрий, не сочти за труд, пожалуйста, создай тему "В поиске правильной модели WS клиента" в разделе Интеграция (этот вопрос явно заслуживатеся отдельной темы), и опиши в качестве исходного примера работу этого сервис-клиента (словами или UML схемой).
Den, не стесняйся, создавай любые темы которые считаешь нужными. Если честно я уже должен тебе деньги платить за созданные тобой темы
Вот тут увидел - наши коллеги постарались сделать видео по теме ООП Шаблоны Проектирования ООП на Apex
спасибо, посмотрел. неплохая презентация, но есть несколько комментов:
(1) по синглтону: а как все-таки правильнее получать Рек Тайп ID: - просто кверить; или - как предложено там: Object__c.sObjectType.getDescribe().getRecordTypeInfosByName().get("sample").getRecordTypeID();
а оборачивать таким образом полученные АйДи в синглтонированный объект имеет смысл только если с этим АйДи нужно "носиться" по всему экзекюшен контектс ( получили АйДи в начале кода, а работаем с ним где-то там, а может много раз), фактически это описано в Адвансед АПЕКС апелмана, но там было без синглтона.
(2) по Стратегии код плохо видно (на 8.18), но как мне кажется внутри стратегии сидит простая Фабрика именно с созданием объекта "от имени", как мы обсуждали выше, и возможно что когда wilder и Gres писали что используют такую фабрику, они имелии виду именно такую Стратегию. Фактически отличие такой Стратегии от простой Фабрики - это то что тут стратегия заставлется созданние объекты что-то делать. Жаль, что автор привел пример вроде как на Апексе, но совершенно абстрактный.
(3) Декоратор - без вопросов.
(4) Фасад, все понятно, и пример с WS клиентом хороший, возможно тот сложный WS клиент, о котором упоминал Дмитрий выше - именно так и работает.
(5) Композит - как то скомкано получилось, надо еще разбираться.
(6) Bulk State Transition - это даже не патерн - это первая вещь котрую должен понять СФ разработчик. (пачечная обработка записей в тригере, когда в самом тригере собирается требуемая дата (обычно IDs), а потом одним листом подается в метод какого-то класса).
strategies = new Map<String,GeocodeService>(); for(String name : strategyNames){ try{strategies.put(name, (GeocodeService)Type.forName(name).newInstance());} catch(Exception e){continue;} //skip bad name silently on init stage } }
private GeocodeService strategy;
public Geocoder(String name){ if(!strategies.containsKey(name)) throw new NameException(name); //show bad name if it does not exist (or was skiped in init stat section) strategy = strategies.get(name); }
public List<Double> getLatLong(String address){ return strategy.getLatLong(address); }
}
всем хороша, но если присмотреться, то главная Мапа
public static final Map<String,GeocodeService> strategies;
содержит инициализированные объекты, и при этом класс в принципе может использовать только один из них.
немного переписал: теперь главная Мапа содержит Type и вместо конструктора добавил метод, который может переключать логику у текущего объекта на ходу:
strategies = new Map<String,Type>(); for(String name : strategyNames){ try{strategies.put(name, Type.forName(name));} catch(Exception e){continue;} //skip bad name silently on init stage } }
private GeocodeService strategy;
public List<Double> getLatLong(String address){ return strategy.getLatLong(address); }
public Geocoder2 SetLogic(String name){
if(!strategies.containsKey(name)) throw new NameException(name); //show bad name if it does not exist (or was skiped in init stat section)
Type myType= strategies.get(name);
strategy = (GeocodeService) myType.newInstance();
return this; }
}
теперь с объектом можно так работать:
Geocoder2 geocoder = new Geocoder2().setLogic('GoogleMapsImpl');
Наконец-то я понял, что такая фабрика позволяет расширять (дополнять новыми вариантами действий) какой-то код без малейших изменений в нем. настоящая модульность.
вот у менят есть тригер на Аттачментах, который ловит Аттачи от нескольких объектов и что то делает (делает похожую логику, но немного отличающуюся от объекта к объекту). Проблема в том, что в данном приложении постоянно прибывает объектов, которые должны отработь эту логику. Тригер приходится постоянно дописывать, дописывать тест, тащить все в прод.
А я мог бы в тригере провести начальную проверку условий и передать Аттачи в класс-фабрику, которая по API имени объета-родителя инициировала нужный "рабочий" объект и заставляла его отработать нужную логику.
в таком случае, если в тригер нужно добавить модуль по работе с новым объектом, то просто пишется "рабочий" класс, переносится в Прод, и в кастомный настройкая добавляется подстрока ",NewCustomObject__c". И все.
Наконец-то я понял, что такая фабрика позволяет расширять (дополнять новыми вариантами действий) какой-то код без малейших изменений в нем. настоящая модульность.
вот у менят есть тригер на Аттачментах, который ловит Аттачи от нескольких объектов и что то делает (делает похожую логику, но немного отличающуюся от объекта к объекту). Проблема в том, что в данном приложении постоянно прибывает объектов, которые должны отработь эту логику. Тригер приходится постоянно дописывать, дописывать тест, тащить все в прод.
А я мог бы в тригере провести начальную проверку условий и передать Аттачи в класс-фабрику, которая по API имени объета-родителя инициировала нужный "рабочий" объект и заставляла его отработать нужную логику.
в таком случае, если в тригер нужно добавить модуль по работе с новым объектом, то просто пишется "рабочий" класс, переносится в Прод, и в кастомный настройкая добавляется подстрока ",NewCustomObject__c". И все.
Почитай еще про инъекцию зависимостей и принципы S.O.L.I.D., я думаю, тебе будет очень интересно.
Кст, ты просто читаешь или еще и тренируешься, т.е. пишешь какой-то код? Если пишешь, то можно выложить проект на гитхаб и там запилить набор используемых тобой паттернов.
Кст, ты просто читаешь или еще и тренируешься, т.е. пишешь какой-то код?
читаю, повторяю пример в дев орге, потом думаю: как же его можно применить в реальной текущей работе. иногда ничего не приходит на ум (тогда откладываю в памяти), иногда приходят идеи (как с тригеров выше), но применять буду уже на рабочем проекте, в нерабочее время (как будет), так как это переписывание старого, чужого кода (на это время не дадут). пока выкладывать нет чего
УРА! Теперь и я могу считать себя образованным - нашел как по научному называется принцип проектирования, который использую я KISS
KISS (англ. keep it simple, stupid — буквально — «делай это проще, тупица» или более вежливый вариант англ. keep it short and simple — «делай короче и проще») — процесс и принцип проектирования,[1] при котором простота системы декларируется в качестве основной цели и/или ценности. Имеют хождение разные расшифровки этого акронима. Эрик Рэймонд в своей книге резюмирует философию UNIX как широко используемый принцип KISS.