Код-ревью проекта. С#.Unit testing

начала изучать юнит тесты.

Чтобы попрактиковаться, сделала небольшой проект, суть которого реализация двухсвязного списка и покрытие кода юнит тестами. Использовала MSTests. Хотелось бы получить код-ревью.

Буду рада любому отзыву!

Ссылка на репозиторий: https://github.com/juliion/MyList


Ответы (2 шт):

Автор решения: tym32167

Чтож, хотели ревью, его есть у меня немного.

Проект на гитхабе.

  1. Раз хотите, чтобы вас судили по проекту, озаботьтесь хотя бы описанием нормальным или названием. "MyList" ничего не говорит о проекте.
  2. "Установи dot net" не указывает не конкретную версию. Что конкретно установить?
  3. У вас список фич, было бы неплохо расширить примерами кода
  4. Ссылки на какие то коммиты, где фейлятся какие то тесты - они точно в Readme нужны?
  5. Если есть желание показать, что вы умеете в git, то не стоит пушить в мастер все. У вас только 1 ветка на проект. Но это абсолютно не обязвтельное требование, просто пожелание - держите мастер чистеньким
  6. Не увидел лицензии в репозитории

Код

  1. Названия. Например "List" вообще ничего не говорит о классе. Как насчет "DoubleLinkedList"? "DoubleLinkedListNode"?
  2. Node видится как просто деталь имплементации вашего списка, зачем этот класс вынесен и сделан публичным? По мне так это внутренний приватный класс для класса списка.
  3. Как следствие предыдущего public Node Head { get; private set; } Node не должно покидать List, поле должно хотя бы выглядеть как public char Head => this.HeadNode.Data; Иначе клиенты с вашими нодами сделают все, что захотят и сломают вашу реализацию на раз.
  4. Хотите делать список свой действиельно расширяемым, почему бы тогда не использовать обобщения? DoubleLinkedList<T>?
  5. Если делаете класс для того, чтобы кто то его мог использовтаь - хотя бы xml комментарии вставляйте
  6. Когда делаете класс для переиспользования, делайте для него отдельный проект типа библиотеки. На надо его рядом с Program ложить
  7. var tmp = new Node() избегайте таких названий переменных
  8. public void InsertAt(char val, int ind) не экономьте на буквах, индекс значит index
  9. throw new Exception("Wrong index"); пишите более информативные сообщения об ошибках, типа "параметр под именем индекс имеет неверное значение. Значение параметра -10, допустимые значения от 0 до count"
  10. Качество кода не на высоте, тот же метод public void InsertAt(char val, int ind) запутанный. Я уверен, можно код переписать и сделать его в 3 раза короче и 10 раз понятней. И так для всего кода.
  11. PrintForward() почему список вдруг будет что то печатать на консоль? Позабыли про S из SOLID?
  12. Скорость работы тут явно не в приоритете. Метод Reverse() просто режет глаза.

Тесты

  1. Чтобы проверять, вылезло ли исключение не надо try/catch, надо Assert.ThrowsException
  2. У вас в каждом тесте есть firstElement, secondElement, thirdElement - может сделать из них readonly поля? Да и вообще, вам обязательно их так называть? Да и вообще, вам обязательно их иметь как переменные?
  3. Что понравилось - более менее логичное и консистентное наиманование тестов (что тестируем _ сценарй _ результат)

Резюмируя, не все так плохо. Для новичка в программировании, того, кто только учится на джуна - неплохо. Видно, что где то старались (тестов накидать), где то забили совсем (название проекта, например), что в среднем получаем оценку удовлетворительно. Что не плохо, но может быть и лучше.

→ Ссылка
Автор решения: Alexander Tolstikov
  1. Публичный доступ к Node нарушает инкапсуляцию, в идеале пользователям Вашей коллекции нужно знать как можно меньше деталей и скорее всего им будет достаточно использовать лишь API класса List;

  2. PrintForward нарушает Single Responsibility Principle (см. SOLID), лист не должен знать как себя выводит и тащить за собой зависимость консоли, это не его ответственность поэтому её следует реализовать в другом месте (в подовляющем большинстве случаев);

  3. Название List слегка вводит в заблуждение пользователей вашего кода, возможно стоит назвать его DoubleLinkedList;

  4. Почитайте о подхода к стайлингу в коде, попробуйте использовать статические анализаторы кода, например Stylecop;

  5. Попробуйте реализовать паттерн итератор поверх вашей коллекции (см. IEnumerable, IEnumerator интерфейсы);

  6. Попробуйте абстрагировать от типа хранимых данных используя Generics вместо хранения элементов типа char;

  7. Почитайте о best practise о том как вести собественный репозиторий;

  8. Напишите тесты на Ваш клас для публичного АПИ, чтобы показать другим о том что Вашим классом можно пользоваться и как это делать;

  9. Добавьте Summary на публичный АПИ класса;

  10. Попробуйте интегривать ваш репозиторий с CI системой, например GitHub actions;

  11. Посмотрите чужие репозитории чтобы понять как вашу задачу решили другие;

  12. Попробуйте минимизировать АПИ вашего класса до наиболее низкоуровневого решающего поставленную задачу, а все ништяки увести в extensions methods, таким образом вы покажите пример как с Вашим классам работать и расширять его варианты использования.

Много всего другого, но можете начать с этого. А вообще, совет по практике, порешайте простые алгоритмические задачи на общедоступных ресурсах, например на Leetcode/Codewars. А дальше попытайтесь писать простые проекты на основе туториалов. Все понемногу придет с опытом, главное упорство и внутренний интерес, удачи!

→ Ссылка