|
|
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
Здравствуйте форумчане. Сначала опишу задачу нужно написать метод, который принимает на вход две коллекции(не уточняется какие) объектов и возвращает объединенную по определенным правилам коллекцию с этими же объектами. Объект - это цена на товар, имеет следующие поля long id; // идентификатор в БД String product_code; // код товара int number; // номер цены int depart; // номер отдела Date begin; // начало действия Date end; // конец действия long value; // значение цены в копейках объединять нужно с учетом таких условий у товара с одним кодом может быть несколько номеров цены, товар с тем же кодом и номером цены может быть в разных отделах. Но в одном отделе с одинаковым номер и кодом товара может быть только одна цена. пример: Product_code Number Depart Begin End valueИмеющиеся цены122856 1 1 01.01.2013 00:00:00 31.01.2013 23:59:59 11000122856 2 1 10.01.2013 00:00:00 20.01.2013 23:59:59 990006654 1 2 01.01.2013 00:00:00 31.01.2013 00:00:00 5000Новые цены122856 1 1 20.01.2013 00:00:00 20.02.2013 23:59:59 11000122856 2 1 15.01.2013 00:00:00 25.01.2013 23:59:59 920006654 1 2 12.01.2013 00:00:00 13.01.2013 00:00:00 4000Результат:122856 1 1 01.01.2013 00:00:00 20.02.2013 23:59:59 11000122856 2 1 10.01.2013 00:00:00 15.01.2013 00:00:00 99000122856 2 1 15.01.2013 00:00:00 25.01.2013 23:59:59 920006654 1 2 01.01.2013 00:00:00 12.01.2013 00:00:00 50006654 1 2 12.01.2013 00:00:00 13.01.2013 00:00:00 40006654 1 2 13.01.2013 00:00:00 31.01.2013 00:00:00 5000 Суть в том что данные в старом и новом списках естественно могут и будут несовпадать в отличие от примера. В новом списке могут быть новые коды(добавляем в объединенный) или в новом отсутствуют старые(переносим в объединенный старые данные) Я решил делать следующим образом: 1)берем из текущего списка первый объект, берем код продукта 2)получаем из текущего списка подмножество объектов с текущим кодом 3)берем объект уже из списка с текущим кодом, берем номер цены 4)подмножество с номером цены из подмножества с текущим объектом 5)из списка с номером - объект с отделом, номер отдела 6)подмножество с номером отдела (здесь в идеале должен быть 1 объект, как в списке текущих так и новых цен и уже конкретно эти объекты сравниваем между собой по датам и формируем новые объекты в соответствии в требованиями) Если писать "в лоб" получается очень много похожего кода в котором легко запутаться, я вынес часть в отдельный метод, стало получше, но все равно не очень. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. После того как подмножество обработано, чтобы не натыкаться на повторяющиеся данные я планирую удалять их из списков полученных на вход removeAll(текущее подмножество); Таким образом в конце обработки входные коллекции должны оказаться пустыми. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.09.2017, 20:34 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
archelite, На больших списках тормозит? Варианты: - в субд sql' ем - паттерн Визитор. ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 07:34 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
archelite, Вы зачем-то намешали в свой вопрос кучу барахла из предметной области, которая тут никому не интересна. Отчего понять ваш вопрос становится сложно. archeliteу товара с одним кодом может быть несколько номеров цены, товар с тем же кодом и номером цены может быть в разных отделах. Но в одном отделе с одинаковым номер и кодом товара может быть только одна цена. За такую формулировку надо эксперту предметной области чем-то тяжелым по голове бить. "Может быть", а "может и не быть" ничего не говорят о том что мы должны получить в результате. И что делать с дупликатами. И вообще больше вопросов чем ответов. Абстрагируйтесь от предметной области. Есть два списка объектов. Нужно сформировать объединение этих списков, но по каким-то признакам объекты могут считаться идентичными их в списке быть не должно. Соответсвенно поля которые влияют на идентичность это в данном контексте - ключ объектов. Вам нужно разделить объект на ключ и остальные данные. Для того чтобы получить уникальные объекты нужно поместить их в HashMap по ключу. Если нужно как-то комбинировать объекты с идентичным ключом, для этого есть метод Map.merge(key, value, remappingFunction) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 09:14 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
Petro123, авторНа больших списках тормозит? - в субд sql' ем - паттерн Визитор. Смотря что считать большими списками Это тестовое задание, так что нужно в коде) Хз как его применить потому что точно неизвестно по каким критериям сравнивать объекты Blazkowicz, В целом вы пересказали мои мысли по этому вопросу, я тоже сначала подумал про мапу и ключи, но из за несколько размытого условия непонятного как это сделать. Есть еще метод retainAll но он сравнивает по equals'у а мне бы по компаратору, но в стандартном API я такого не нашел. У меня есть решение для частного случая, когда каждому объекту есть одно соответствие, а решение для всех возможных случаев получается громоздкое. В обычном случае я бы просто уточнил условия, а это тестовая задача, уточнять как то немного неловко, хотя может они специально так сформулировали. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 11:17 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
archeliteВ целом вы пересказали мои мысли по этому вопросу Телепаты в отпуске. Если не хотите пересказа своих мыслей, то стоило их опубликовать. archelite я тоже сначала подумал про мапу и ключи, но из за несколько размытого условия непонятного как это сделать. Фраза "Я решил делать следующим образом:" намекает на то что вам всё понятно. Вопроса "чтобы авторы задачи могли иметь ввиду?" я тоже не вижу. archelite Есть еще метод retainAll но он сравнивает по equals'у а мне бы по компаратору, но в стандартном API я такого не нашел. Направление мысли правильное. Проблема с вычислением equals/hashCode снаружи объекта легко решается новым объектом. archeliteУ меня есть решение для частного случая Это жопа какая-то а не решение. Копипаст на копипасте. Нолики и единички. Куча ни о чем не говорящих идентификаторов. Я уже не говорю про количество кода для решения примитивной задачи. Введение нового поля в ключ у вас приведёт к очередной копипасте кучи блоков кода? archelite, когда каждому объекту есть одно соответствие Что такое одно соответствие? Чем оно отличается от многих? archelite, а решение для всех возможных случаев получается громоздкое. Если ограничивать себя использованием if...else и массивами, то да. Но как-то JSE API пообширнее будет. Я в таком виде свою первую программу писал. Крестики-нолики. Меня хватило только на реализацию первого хода. Это была копипаста из 9 возможных вариантов. Если бы я и дальше писал в этом стиле, то на каждый из возможных состояний поля у меня бы была схожая секция кода. С тех пор я всегда переиспользую код (до тех пор пока копипаста не приводит к более простому коду, чем полноценная абстракция). И вам советую. archeliteВ обычном случае я бы просто уточнил условия, а это тестовая задача, уточнять как то немного неловко, хотя может они специально так сформулировали. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Я бы ещё больше заморочился - ProductPriceMergeKey отделил бы от ProductPrice, а передавал туда только getter-ы через лямбды. Код: java 1. 2. 3. 4. 5. 6. 7. 8. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 11:58 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
Blazkowicz Код: java 1. 2. 3. 4. 5. 6. 7. 8. instance тут не нужен по-идее. Мы его не явно через геттеры протащим. Просто иногда бывает нужно использовать Function вместо Supplier чтобы вызывать их для разных instance. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 12:02 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
archeliteОбъект - это цена на товар, имеет следующие поля long id; // идентификатор в БД String product_code; // код товара int number; // номер цены int depart; // номер отдела Date begin; // начало действия Date end; // конец действия long value; // значение цены в копейках объединять нужно с учетом таких условий у товара с одним кодом может быть несколько номеров цены, товар с тем же кодом и номером цены может быть в разных отделах. Но в одном отделе с одинаковым номер и кодом товара может быть только одна цена.Эх, Petro123 выше дело говорит, а вы его не слушаете... Код: sql 1. 2. 3. 4. 5. 6. Это для оракла, под вашу СУБД сами как-нибудь перепишете... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 12:17 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
archelite Сначала опишу задачу нужно написать метод... Классическая ошибка в постановке целей. У вас нет задачи написать метод. У вас есть задача выполнить тестовое задание. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 12:29 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, авторclass ProductPriceMergeKey { final Product product public ProductPriceMergeKey (Product product){...} //Вычисляем используя только нужные поля product int hashCode(){...} boolean equals(){...} Map<Product> map = prices.stream().collect(toMap(p -> new ProductPriceMergeKey(p), p->p)); newPriceMap.forEach((k, p) -> oldPriceMap.merge(k, p, (newPrice, oldPrice) -> newPrice.merge(oldPrice)); } Спасибо за пример, распилил на 2 сущности, данные по которым сравниваю - в key, по которым мержить в value. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Осталось улучшить метод, который в зависимости от дат пилит новые объекты. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. Нужно сравнить между собой начальную, конечную даты и цену, в зависимости от результатов создавать новые объекты. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 17:40 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
С трудом пытаюсь подобрать слова, потому что кроме матов в голове только название книги Clean Code by Robert C Martin. Вы правда не знаете что скопировать\вставить это худший способ переиспользовать код. И что править в таком коде баги мучительно больно, потому что их придется править в каждой копии, которую вы создали. А ещё более мучительно в такой код добавлять изменения... По делу напишу позже, когда глаза перестанут кровоточить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 18:02 |
|
||
|
Рефакторинг/Применение паттернов
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Ваши основные ошибки в методе mergePrices(). 1. Метод оперирует исключительно полями класса Price. Поэтому он должен находится в классе Price. А не где-попало. Вы нарушаете инкапсуляцию. 2. Независимо от сценария, вам нужно вызывать метод .add() и конструктор new Prices(). Так с какого перепуга эти методы вызывать в каждом сценарии отдельно. А не один раз и для любого сценария? 3. Ваш код абсолютно не читаем. Какой нормальный человек сходу поймет это условие curPrice.begin.compareTo(newPrice.begin) == -1 && curPrice.end.compareTo(newPrice.end) == 1 ? Условия тоже нужно инкапсулировать в отдельные методы. Причем методы должы совпадать с названиями этих сценариев в предметной области. Например: curPrice.intersectDatesOf(newPrice) curPrice.olderThan(newPrice) 4. Я понимаю что лямды и стримы для новичка это не так просто. Но не использовать Java 8 Date/Time API для сравнения и манипуляций временем это, я считаю, большое упущение. 5. Вы спрашивали про паттерны. Так вот copy constructor это паттерн, которого тут так не хватает. 6. Инкремент идентификатора БД на уровне Java - очень сомнительное решение. В итоге мы получаем. Что в зависимости от двух периодов, нам нужно получить список новых периодов и из них сформировать копии объектов. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.09.2017, 18:44 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=39516349&tid=2122608]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
52ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
54ms |
get tp. blocked users: |
1ms |
| others: | 223ms |
| total: | 372ms |

| 0 / 0 |
