Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Юнит тесты для "системного" приложения

2301  1 2 3 4 5 6 7 8 9 все
MrSanders коренной житель18.04.21 20:29
NEW 18.04.21 20:29 
в ответ AlexNek 18.04.21 19:57
То бишь в "главный класс" нужно передать минимум 3 совершенно не нужных параметра, а с экспортом и 4. Соответственно и количество лишних интерфейсов возрастает.
В общем, KISS - пошел нафиг.

Насчёт ненужных я бы поспорил. И насчёт нарушения KISS. Если компрессор и мувер не передаются снаружи значит что? Значит класс такой "умный" что сам знает как их сделать. Во-первых это сложнее чем получить их снаружи. Во-вторых это а. дополнительная ответственность и б. нарушение open-close. Аж две буквы из SOlid поломали.

AlexNek патриот18.04.21 21:03
AlexNek
NEW 18.04.21 21:03 
в ответ MrSanders 18.04.21 20:29
Аж две буквы из SOlid поломали.

У меня есть одна проблема - не люблю слепо следовать догмам. Не люблю делать универсальных монстров и стрелять из пушки по воробьям.

Если для экспорта еще как то можно представить себе изменения, то для компрессора и мувера - довольно сложно. Вполне достаточно того, что они вынесены в отдельный класс.

Ну и делать конструкторы вьювмоделей с параметрами для ВПФа, тоже не очень хорошо.


Тем более, что прога не идет в промышленную эксплуатацию на многие годы.


Программист коренной житель18.04.21 21:15
NEW 18.04.21 21:15 
в ответ AlexNek 18.04.21 21:03, Последний раз изменено 18.04.21 21:17 (Программист)
Ну и делать конструкторы вьювмоделей с параметрами для ВПФа, тоже не очень хорошо.

Почему это?


Тем более, что прога не идет в промышленную эксплуатацию на многие годы.

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


AlexNek патриот18.04.21 21:28
AlexNek
NEW 18.04.21 21:28 
в ответ Программист 18.04.21 21:15
Почему это?

Добавь в подобную конструкцию еще параметры смущ


<Window.DataContext>
        <local:CustomViewModel />
</Window.DataContext>
...
<Window.Resources>
        <local:MyViewModel x:Key="MyViewModel"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource MyViewModel}">
    </Grid>
<pre>


от тебя хотят увидеть

Скорее услышать. Времени то челу дали всего час. Кто то за час всё сделает?

Программист коренной житель18.04.21 21:50
NEW 18.04.21 21:50 
в ответ AlexNek 18.04.21 21:28
Добавь в подобную конструкцию еще параметры

Ну просто инициализируешь ViewModel не в XAML, а в code behind, а именно:

     InitializeComponent();
     DataContext = new CustomViewModel(what-ever);


не вижу в этом никакой проблемы.


Скорее услышать. Времени то челу дали всего час. Кто то за час всё сделает?

Час конечно маловато. Но подход увидеть вполне можно.

AlexNek патриот18.04.21 22:07
AlexNek
NEW 18.04.21 22:07 
в ответ Программист 18.04.21 21:50
Ну просто инициализируешь ViewModel не в XAML

Получается что следуя одному принципу мы закрываем другие.

Не могу уже вспомнить конкретную проблему, но пришлось специально убирать все параметры из конструктора. Не всегда можно code behind пользовать


Но подход увидеть вполне можно.

Ну сделай эксперимент, что получится сделать за час. Даже на своём компе. Главное - не копипастить смущ

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

Программист коренной житель18.04.21 22:32
NEW 18.04.21 22:32 
в ответ AlexNek 18.04.21 22:07
Получается что следуя одному принципу мы закрываем другие.

Не понял, что мы закрываем?


Не могу уже вспомнить конкретную проблему, но пришлось специально убирать все параметры из конструктора. Не всегда можно code behind пользовать

Не встречал еще ситуации, когда нет code behind.

Если у тебя есть элегантный способ передать настройки во ViewModel, то было бы интересно посмотреть на этот способ. А то я эля таких ситуаций использую параметры контруктора :)


Ну сделай эксперимент, что получится сделать за час.

Честно говоря, мне лень :) Думаю, что в течении дня я бы сделал то задание.


koder патриот19.04.21 06:14
koder
NEW 19.04.21 06:14 
в ответ AlexNek 18.04.21 16:02, Последний раз изменено 19.04.21 06:21 (koder)
Может быть я еще неправильно представляю себе как делать моки?


Где то вот так


@Mock

Copressor copressor


Все. теперь обьект, которыj создаст библиотека мокито, можно использоват'

koder патриот19.04.21 06:20
koder
NEW 19.04.21 06:20 
в ответ AlexNek 18.04.21 19:57
То бишь в "главный класс" нужно передать минимум 3 совершенно не нужных параметра, а с экспортом и 4. Соответственно и количество лишних интерфейсов возрастает.

Не надо. Технологии WhiteBox, инектирование, подмена переменных класса во время выполнения. Это можно делать даже для приватных переменных. Но переменные можно делать наследуемыми и тестировать наследников класса с дополнительными сеттерами.Есть много способов внедрить мок вместо реального обьекта. А вот если нельзя, значит в классе проблемы. И функциональный и инитиализатионных код свален в одну кучу.

AlexNek патриот19.04.21 12:41
AlexNek
NEW 19.04.21 12:41 
в ответ Программист 18.04.21 22:32
Не понял, что мы закрываем?

Ну хотя бы инициализацию из ХАМЛа. Как передать во вьюв-модель из ХАМЛа что-то кроме строки я не знаю.


Не встречал еще ситуации, когда нет code behind.

Тоже было до поры до времени, пока более сложный UI не понадобился.


Если у тебя есть элегантный способ передать настройки во ViewModel

Они просто идут вторым шагом, через сервис например или через сообщения.


Думаю, что в течении дня я бы сделал

Я тоже так думал, но не получилось. смущ Там проблем больше чем вначале думаешь.

Но возьми даже 1/8 часть готового приложения, что это будет в итоге?

AlexNek патриот19.04.21 12:43
AlexNek
NEW 19.04.21 12:43 
в ответ koder 19.04.21 06:20
Есть много способов внедрить мок вместо реального обьекта

Я пока знаю только тот, который описал. Поищем другие "либы".

Программист коренной житель19.04.21 13:02
NEW 19.04.21 13:02 
в ответ AlexNek 19.04.21 12:41
Они просто идут вторым шагом, через сервис например или через сообщения.

Ну так и DI можно также делать ;)

AlexNek патриот19.04.21 13:03
AlexNek
NEW 19.04.21 13:03 
в ответ MrSanders 18.04.21 20:29
Во-вторых это а. дополнительная ответственность

Вот другая проблема есть, решение которой мне совершенно не нравиться, но пока не могу придумать лучше.


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

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

Каждая операция реализована как вызов функции из дополнительного класса. Но вот эти все вызовы расположены в одном месте и они все разные.

С одной стороны это файловый операции, а с другой стороны, добавление новых элементов в UI и их сохранение.


Хотелось, хотя бы отделить файловые операции и UI, только как тогда информировать нужный UI элемент об ошибке.

AlexNek патриот19.04.21 13:19
AlexNek
NEW 19.04.21 13:19 
в ответ Программист 19.04.21 13:02
Ну так и DI можно также делать

Если речь идёт о DI Container/Frameworks, то я их пока не переношу.

Когда всё приложение так построено, разобраться в его работе очень сложно.

Так поставил точку останова в конструкторе и знаешь кто и откуда вызвал. А с контейнером поди еще найди как эта инстасе получается т откуда пришел вызов.

Программист коренной житель19.04.21 13:22
NEW 19.04.21 13:22 
в ответ AlexNek 19.04.21 13:19
Если речь идёт о DI Container/Frameworks, то я их пока не переношу.

Нет, речь о том, что все зависимости можно устанавливать точно также как и передовать конфигурацию во ViewModel.

AlexNek патриот19.04.21 14:08
AlexNek
NEW 19.04.21 14:08 
в ответ Программист 19.04.21 13:22
то все зависимости можно устанавливать точно также как и передовать конфигурацию

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

Программист коренной житель19.04.21 14:14
NEW 19.04.21 14:14 
в ответ AlexNek 19.04.21 14:08

От куда ты взял универсального монстра? Ты как-то не так понимаешь DI улыб

AlexNek патриот19.04.21 14:42
AlexNek
NEW 19.04.21 14:42 
в ответ Программист 19.04.21 14:14
Ты как-то не так понимаешь DI

Может быть. У меня есть просто различия, когда нужно, а когда нет. А не только - исключительно всё на интерфейсах внутри, а снаружи вся имплементация.

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

Хочешь менять - меняй, всё в отдельном классе. Когда понадобится вторая имплементация, можно будет сделать, но никак не раньше того, чем вероятно может понадобится или понадобилось.

В данном случае - вероятность изменений практически нулевая.


Программист коренной житель19.04.21 15:45
NEW 19.04.21 15:45 
в ответ AlexNek 19.04.21 14:42
Ну зачем мне ещё добавлять "интерфейс компрессии файла" и выводить его наружу?

Ну тут есть несколько моментов:

1) для того, чтобы код был тестируемым.

2) чтобы класс отвечал только за то, чем он занимается. И не занимался 2-мя, 3-мя и более вещами. Single Responsibility.

3) расширяемость


У меня есть просто различия, когда нужно, а когда нет.

Ну просто для тебя "нужно" - это только расширяемость :) Но на самом деле расширяемость - это просто побочная плюшка :D


MrSanders коренной житель19.04.21 16:11
NEW 19.04.21 16:11 
в ответ AlexNek 19.04.21 13:03
Хотелось, хотя бы отделить файловые операции и UI, только как тогда информировать нужный UI элемент об ошибке.

Event-ы наше всё!

1 2 3 4 5 6 7 8 9 все