тестовое задание
От: mig84 Россия  
Дата: 05.12.13 15:32
Оценка:
Здравствуйте. Не так давно выполнил (во всяком случае так считал) тестовое задание. Описание задачи:
Спроектируйте и реализуйте класс-коллекцию для хранения элементов, имеющих уникальный составной ключ [Id, Name] (Id и Name – компоненты ключа, могу быть произвольного типа). Вы можете использовать любую встроенную коллекцию .NET Framework.
Предоставьте необходимые с вашей точки зрения методы для этой коллекции, а так же методы для эффективного по скорости получения элементов по их Id ИЛИ Name.
Программа должна содержать пример использования коллекции с идентификатором ключа в виде пользовательского типа (т.е. Id в ключе – UserType, объекты UserType должны сравниваться по значению).
Дополнительно: Создайте потокобезопасную реализацию этой коллекции (не использовать коллекции из пространства имён System.Collections.Concurrent).

То, что я предложил в качестве решения:


Элемент и UserType:

    /// <summary>
    /// Элемент коллекции
    /// </summary>
    public class MyElement
    {
        private UserType id;
        private String name;

        public String Name
        {
            get { return name; }
            set { name = value; }
        }

        public UserType Id
        {
            get { return id; }
            set { id = value; }
        }

        public override int GetHashCode()
        {
            return Name.GetHashCode() ^ Id.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (!(obj is MyElement))
            {
                MyElement el = (MyElement)obj;
                return Id == el.Id && Name == el.Name;
            }
            else
            {
                return false;
            }
        }

        public override string ToString()
        {
            return String.Format("Id:{0}, Name:{1}",id.Content.ToString(), Name);
        }

    }
    /// <summary>
    /// Тип для поля Id
    /// </summary>
    public struct UserType
    {
        private int content;
        public int Content
        {
            get { return content; }
            set { content = value; }
        }

        public override int GetHashCode()
        {
            return Content^Content;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is UserType))
            {
                UserType ut = (UserType)obj;
                return Content == ut.Content;
            }
            else
            {
                return false;
            }
        }

        public static Boolean operator == (UserType ut1, UserType ut2)
        {
            return ut1.Content == ut2.Content;
        }

        public static Boolean operator != (UserType ut1, UserType ut2)
        {
            return ut1.Content != ut2.Content;
        
        }

        public override string ToString()
        {
            return Content.ToString();
        }

    }


Индекс:

    /// <summary>
    /// Индекс для коллекции
    /// </summary>
    public struct MyId : IEquatable<MyId>
    {
        private readonly UserType id;
        private readonly String name;

        public UserType Id
        {
            get
            {
                return id;
            }
        }

        public String Name
        {
            get
            {
                return name;
            }
        }

        //public MyId(UserType _id, String _name)
        //{
        //    id = _id;
        //    name = _name;
        //}

        public MyId(MyElement element)
        {
            id = element.Id;
            name = element.Name;
        }

        public override int GetHashCode()
        {
            return id.GetHashCode() ^ name.GetHashCode();
        }

        public bool Equals(MyId other)
        {
            if ((object)other == null)
            {
                return false;
            }
            else
            {
                return id == other.id && name == other.name;

            }
        }

        public override bool Equals(object obj)
        {
            return Equals((MyId)obj);
        }

        public static Boolean operator == (MyId u1, MyId u2)
        {
            return (u1.id == u2.id) && (u1.name == u2.name);
        }

        public static Boolean operator != (MyId u1, MyId u2)
        {
            return (u1.id == u2.id) || (u1.name == u2.name);
        }

        public override string ToString()
        {
            return String.Format("Key(id={0}, name={1})", id.ToString(), name);
        }
    }


Собственно, коллекция:
    /// <summary>
    /// Класс-коллекция. Потокобезопасность реализована для метода Add.
    /// Т.к. коллекция наследует от Dictionary, она поддерживает необходимые базовые методы
    /// </summary>
    /// <typeparam name="TKey">В качестве ключа используется MyId</typeparam>
    /// <typeparam name="TValue">Элемент коллекции</typeparam>
    public class MyCollection<TKey, TValue> : Dictionary<MyId, TValue>
    {
        private readonly object syncRoot = new object();
        private Dictionary<MyId, TValue> _myCollection = new Dictionary<MyId, TValue>();


        /// <summary>
        /// Перекрываем метод вставки в коллекцию для реализации потокобезопасности.
        /// Примечание: при попытка вставить элемент с повторяющимся индексом просто игнорируем вставку.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public new void Add(MyId key, TValue value)
        {
            lock (syncRoot)
            {
                if (!this.ContainsKey(key))
                {
                    base.Add(key, value);
                }
                
            }

        }

        #region Реализация методов поиска указанных в задании

        public MyElement GetElementById(UserType _id)
        {
            dynamic result;
            lock (syncRoot)
            {
                result = this.Where(x => x.Key.Id == _id).SingleOrDefault().Value;
            }
            if (result is MyElement)
            {
                return result as MyElement;
            }
            else
            {
                return null;
            }
        }

        public MyElement GetElementByName(String _name)
        {
            dynamic result;
            lock (syncRoot)
            {
                result = this.Where(x => x.Key.Name == _name).SingleOrDefault().Value;
            }

            if (result is MyElement)
            {
                return result as MyElement;
            }
            else
            {
                return null;
            }

        }

        public MyElement GetElementByIdOrName(object o)
        {
            if (o is String)
            {
                return GetElementByName((string)o);
            }
            else if (o is UserType)
            {
                return GetElementById((UserType)o);
            }
            else
            {
                return null;
            }
            
        }

        #endregion

    }


Этот вариант решения, как видно, не понравился проверявшему.
Буду признателен, если "ткнете носом" в ошибки. Понимаю, что, возможно подошел к решению довольно формально, но по требованиям вроде все реализовал. Или чего-то не так понял.
Re: тестовое задание
От: Хэлкар  
Дата: 05.12.13 15:41
Оценка: 2 (1) +1
UserType.getHashCode() будет всегда давать 0. Ты число само с собой суммируешь.
Re[2]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 15:42
Оценка:
Огромное количество мест, где может вылететь NRE.
Re: тестовое задание
От: Vzhyk  
Дата: 05.12.13 15:44
Оценка: +3 -2
12/5/2013 6:32 PM, mig84 пишет:

> Этот вариант решения, как видно, не понравился проверявшему.

> Буду признателен, если "ткнете носом" в ошибки. Понимаю, что, возможно
> подошел к решению довольно формально, но по требованиям вроде все
> реализовал. Или чего-то не так понял.
Сколько раз уже здесь срачи на эту тему были. Возможно нафиг им никто не
нужен, возможно кто-то сильно меньше тебя попросил, возможно знакомый
пришел и т.д.

З.Ы. Для тебе это сложно было? Ты много времени потратил? Тебе так важно
устроиться в гадюшник, где даже не соизволили тебе высказать свое мнение
о том, что ты написал? Потому, как это хамство дать человеку делать
тестовое задание и не отвечать и в работе там 100% такой же хамский
подход принят.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 15:47
Оценка:
Для быстрого поиска под id или name лучше бы иметь две хэш-таблицы. Вообще непонятно причем тут составной ключ, если получать данные предпологается только по отдельным частям ключа.
Re[2]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:12
Оценка:
V>З.Ы. Для тебе это сложно было? Ты много времени потратил? Тебе так важно
V>устроиться в гадюшник, где даже не соизволили тебе высказать свое мнение
V>о том, что ты написал? Потому, как это хамство дать человеку делать
V>тестовое задание и не отвечать и в работе там 100% такой же хамский
V>подход принят.

Да, собственно я все это понимаю.
Времени потратил на это совсем немного, но просто любопытны соображения проверяющих.
Re[2]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:18
Оценка:
Х>UserType.getHashCode() будет всегда давать 0. Ты число само с собой суммируешь.

+1 действительно пропустил. Спасибо.
Модифицируем до:


return Content^Content * 127;
Re[3]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 16:20
Оценка:
Здравствуйте, mig84, Вы писали:

Х>>UserType.getHashCode() будет всегда давать 0. Ты число само с собой суммируешь.


M>+1 действительно пропустил. Спасибо.

M>Модифицируем до:


M>
M>return Content^Content * 127;
M>


1. зачем?
2. потенциальное переполнение.
Re[3]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:21
Оценка:
Х>Огромное количество мест, где может вылететь NRE.

Например?
Re: тестовое задание
От: mogikanin Россия  
Дата: 05.12.13 16:24
Оценка: +3
Здравствуйте, mig84, Вы писали:

M>Здравствуйте. Не так давно выполнил (во всяком случае так считал) тестовое задание. Описание задачи:

M>Этот вариант решения, как видно, не понравился проверявшему.
M>Буду признателен, если "ткнете носом" в ошибки. Понимаю, что, возможно подошел к решению довольно формально, но по требованиям вроде все реализовал. Или чего-то не так понял.

Был бы я проверяющим — тоже бы не понравилось. Слишком сложно сделано, много ляпов, да и задание не выполнено. Код джуниора.

1. Id и Name – компоненты ключа, могу быть произвольного типа — этого нет. У вас Id и Name типа string
2. public new void Add(MyId key, TValue value) — зачем вам new? так следует делать только в экстренных случаях
3. lock вообще используется в случайных местах и неоптимально
4. Вот это вообще жесть какая-то.
 if (result is MyElement)
            {
                return result as MyElement;
            }
            else
            {
                return null;
            }
Re[4]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:24
Оценка:
Х>1. зачем?
Х>2. потенциальное переполнение.

В принципе согласен. Можно ограничиться значением Content.
Re[4]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 16:26
Оценка:
В MyElement оба поля могут быть null — GetHashCode и ToString упадут. Аналогично в MyId.
Re[2]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 16:34
Оценка: +1
Охм, посмотрел GetElementById и GetElementByName — зачем там dynamic???
Re[2]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:37
Оценка:
M>1. Id и Name – компоненты ключа, могу быть произвольного типа — этого нет. У вас Id и Name типа string
M>2. public new void Add(MyId key, TValue value) — зачем вам new? так следует делать только в экстренных случаях
M>3. lock вообще используется в случайных местах и неоптимально
M>4. Вот это вообще жесть какая-то.
M>
M> if (result is MyElement)
M>            {
M>                return result as MyElement;
M>            }
M>            else
M>            {
M>                return null;
M>            }
M>


Спасибо за комментарий!
1. "Произвольного типа" можно трактовать по разному. Скорее всего тут Вы правы, действительно имелось ввиду generic.
2. Каким образом иначе можно реализовать потокобезопасность при вставке? Можно было бы обойтись Concurent коллекцией, но по заданию — нельзя.
3. lock оправдан в методе Add (на мой взгляд). В GetElementById — лишний.
4. Да, не оптимально. Можно было одной строкой обойтись.
Re[5]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:39
Оценка:
Х>В MyElement оба поля могут быть null — GetHashCode и ToString упадут. Аналогично в MyId.

Логично. Спасибо. Тестировал коллекцию нормальными элементами. Про такой случай действительно не подумал.
Re[3]: тестовое задание
От: mig84 Россия  
Дата: 05.12.13 16:44
Оценка:
Здравствуйте, Хэлкар, Вы писали:

Х>Охм, посмотрел GetElementById и GetElementByName — зачем там dynamic???


А почему бы и нет? ))) Просто поменять на MyElement забыл.
Re: тестовое задание
От: Ромашка Украина  
Дата: 05.12.13 16:59
Оценка: 4 (1) +3
Здравствуйте, mig84, Вы писали:

Я лично закончил бы общение после этой строки:

M>
M>        public MyElement GetElementById(UserType _id)
M>


M>по требованиям вроде все реализовал. Или чего-то не так понял.


Ты не понял что такое составной ключ и на кой черт он нужен.


Всё, что нас не убивает, ещё горько об этом пожалеет.
Re[3]: тестовое задание
От: mogikanin Россия  
Дата: 05.12.13 17:01
Оценка: 2 (1) +1
Здравствуйте, mig84, Вы писали:

M>Спасибо за комментарий!

M>1. "Произвольного типа" можно трактовать по разному. Скорее всего тут Вы правы, действительно имелось ввиду generic.
Имелось в виду generic.
M>4. Да, не оптимально. Можно было одной строкой обойтись.
Дело не в строках, дело в подходе.

От вас наверняка ждали что-то вроде

    class KeyValueHolder<TId, TName, T>
    {
        private int _count;
        private readonly Dictionary<TId, Dictionary<TName, T>> _dicById;
        private readonly Dictionary<TName, Dictionary<TId, T>> _dicByName;

        public KeyValueHolder()
        {
            _dicById = new Dictionary<TId, Dictionary<TName, T>>();
            _dicByName = new Dictionary<TName, Dictionary<TId, T>>();
        }

        /// <summary>
        /// Получить элементы, имеющие заданный Id
        /// </summary>
        public IList<T> GetById(TId id)
        {
            Dictionary<TName, T> dicName;
            if (!_dicById.TryGetValue(id, out dicName)) return new List<T>();
            return dicName.Values.ToList();
        }

        /// <summary>
        /// Получить элементы, имеющие заданный Name
        /// </summary>
        public IList<T> GetByName(TName name)
        {
            Dictionary<TId, T> dicId;
            if (!_dicByName.TryGetValue(name, out dicId)) return new List<T>();
            return dicId.Values.ToList();
        }

        /// <summary>
        /// Получить элемент по ключу
        /// </summary>
        public T Get(TId id, TName name)
        {
            Dictionary<TName, T> dicName;
            if (!_dicById.TryGetValue(id, out dicName)) return default(T);
            T value;
            if (dicName.TryGetValue(name, out value)) return value;
            return default(T);
        }

        /// <summary>
        /// Добавить элемент
        /// </summary>
        public void Add(TId id, TName name, T value)
        {
            Dictionary<TName, T> dicName;
            if (!_dicById.TryGetValue(id, out dicName))
            {
                dicName = new Dictionary<TName, T>();
                _dicById.Add(id, dicName);
            }
            if (dicName.ContainsKey(name))
            {
                throw new ArgumentOutOfRangeException("name", "Element with given (Id,Name) already exists");
            }

            Dictionary<TId, T> dicId;
            if (!_dicByName.TryGetValue(name, out dicId))
            {
                dicId = new Dictionary<TId, T>();
                _dicByName.Add(name, dicId);
            }
            if (dicId.ContainsKey(id))
            {
                throw new ArgumentOutOfRangeException("name", "Element with given (Id,Name) already exists");
            }

            dicId.Add(id, value);
            dicName.Add(name, value);
            _count++;
        }

        /// <summary>
        /// Удалить элемент
        /// </summary>
        public void Remove(TId id, TName name)
        {
            Dictionary<TName, T> dicName;
            if (!_dicById.TryGetValue(id, out dicName)) return;
            Dictionary<TId, T> dicId;
            if (!_dicByName.TryGetValue(name, out dicId)) return;

            dicId.Remove(id);
            dicName.Remove(name);
            _count--;
        }

        public int Count
        {
            get
            {
                return _count;
            }
        }
    }

  class Program
    {
        static void Main(string[] args)
        {
            var holder = new KeyValueHolder<int, string, string>();
            holder.Add(5, "Петя", "Значение0");
            holder.Add(5, "Вася", "Значение1");
            holder.Add(6, "Вася", "Значение2");
            holder.Add(7, "Вася", "Значение3");
            Debug.Assert(holder.Count == 4);

            var elementsByName = holder.GetByName("Вася");
            var elementsById = holder.GetById(5);

            holder.Remove(7, "Вася");
            Debug.Assert(holder.Count == 3);
        }
    }


Довести до потокобезопасности предлагаю в качестве домашнего задания.
Re[3]: тестовое задание
От: Vzhyk  
Дата: 05.12.13 17:10
Оценка:
12/5/2013 7:12 PM, mig84 пишет:

> Времени потратил на это совсем немного, но просто любопытны соображения

> проверяющих.
Если Хэлкар не тот проверяющий, то соображения у них могут быть любыми.
Но, то что тебе не ответили — это хамство. А хамы обычно всегда хамы.
Posted via RSDN NNTP Server 2.1 beta
Re: тестовое задание
От: samius Япония http://sams-tricks.blogspot.com
Дата: 05.12.13 17:11
Оценка: +1
Здравствуйте, mig84, Вы писали:

M>То, что я предложил в качестве решения:


Кроме уже обозначенного выше еще пара замечаний (не последние, но с остальным лень)

M>
M>    /// <summary>
M>    /// Индекс для коллекции
M>    /// </summary>
M>    public struct MyId : IEquatable<MyId>
M>    {
M>        ...
M>        public bool Equals(MyId other)
M>        {
M>            if ((object)other == null) // <<< Это просто ахтунг!
M>            {
M>                return false;
M>            }
M>            else
M>            {
M>                return id == other.id && name == other.name;

M>            }
M>        }

M>        public static Boolean operator != (MyId u1, MyId u2)
M>        {
M>            return (u1.id == u2.id) || (u1.name == u2.name); // << Копипаста детектед
M>        }
M>
Re[2]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 17:25
Оценка:
Р>Ты не понял что такое составной ключ и на кой черт он нужен.

Я тоже по заданию не понял на кой черт здесь нужен составной ключ.
Re[3]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 17:25
Оценка:
Здравствуйте, Хэлкар, Вы писали:

Р>>Ты не понял что такое составной ключ и на кой черт он нужен.


Х>Я тоже по заданию не понял на кой черт здесь нужен составной ключ.


Можете объяснить?
Re: тестовое задание
От: Nuseraro Россия  
Дата: 05.12.13 17:33
Оценка:
Здравствуйте, mig84, Вы писали:

Вы серьезно? не троллинг?

Полкода лишние и он не делает то, что должен. Даже близко. Много очевидных опечаток. Общий хаос в коде.

Рекомендую внимательнее прочесть задание и сделать значительно больше усилий над разработкой.

А вы уже работали программистом?
Homo Guglens
Re[4]: тестовое задание
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 05.12.13 18:14
Оценка:
Здравствуйте, Хэлкар, Вы писали:

Х>>Я тоже по заданию не понял на кой черт здесь нужен составной ключ.

Х>Можете объяснить?

Спроектируйте и реализуйте класс-коллекцию для хранения элементов, имеющих уникальный составной ключ [Id, Name] (Id и Name – компоненты ключа, могу быть произвольного типа).

Получаем в сишной терминологии
template <typename A, typename B, typename C>
  class our_magic_container_t: private std::map<std::pair<A, B>, C>
{
};


а так же методы для эффективного по скорости получения элементов по их Id ИЛИ Name.

Получаем два метода
template <class Iterator> 
  void our_magic_container::copy_into(const A & id, Iterator pos);
template <class Iterator> 
  void our_magic_container::copy_into(const B & name, Iterator pos);
Re: тестовое задание
От: robin_of_the_wood Россия  
Дата: 05.12.13 18:22
Оценка:
Здравствуйте, mig84, Вы писали:

M>Предоставьте необходимые с вашей точки зрения методы для этой коллекции, а так же методы для эффективного по скорости получения элементов по их Id ИЛИ Name.

...
M>Этот вариант решения, как видно, не понравился проверявшему.
M>Буду признателен, если "ткнете носом" в ошибки. Понимаю, что, возможно подошел к решению довольно формально, но по требованиям вроде все реализовал. Или чего-то не так понял.

Я не очень силен в C# и возможно чего и не понял в коде, но мне показалось что выделенная часть условия не была реализована.
Для уточнения задам простой вопрос.
Допустим я добавил в Вашу коллекцию миллион элементов.
Какое максимальное количество итераций потребуется для поиска элемента по Id и какое по Name?
Проектирование велосипедов для слепых жирафов
Re[5]: тестовое задание
От: Хэлкар  
Дата: 05.12.13 18:49
Оценка:
Собственно в дотнете мы получаем ровно тоже самое. Вопрос — зачем нужен "составной ключ", если мы всегда запрашиваем данные по одному или по другому параметру?
Re: тестовое задание
От: dasha19  
Дата: 05.12.13 19:01
Оценка: -1
о боже, это полный дотнет головного мозга
Re[6]: тестовое задание
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 05.12.13 19:05
Оценка:
Здравствуйте, Хэлкар, Вы писали:

Х>Собственно в дотнете мы получаем ровно тоже самое. Вопрос — зачем нужен "составной ключ", если мы всегда запрашиваем данные по одному или по другому параметру?


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

public MyElement GetElementById(UserType _id)


должно быть заменено на

public IEnumerable<MyElement> GetElementById(UserType _id)


познания в C# не позволяет мне указать произвольный контейнер, куда будут вставлены элементы типа MyElement.
Re: тестовое задание
От: john100  
Дата: 06.12.13 05:06
Оценка:
Здравствуйте, mig84, Вы писали:

M>Здравствуйте. Не так давно выполнил (во всяком случае так считал) тестовое задание. Описание задачи:

M>Спроектируйте и реализуйте класс-коллекцию для хранения элементов, имеющих уникальный составной ключ [Id, Name] (Id и Name – компоненты ключа, могу быть произвольного типа). Вы можете использовать любую встроенную коллекцию .NET Framework.
M>Предоставьте необходимые с вашей точки зрения методы для этой коллекции, а так же методы для эффективного по скорости получения элементов по их Id ИЛИ Name.
M>Программа должна содержать пример использования коллекции с идентификатором ключа в виде пользовательского типа (т.е. Id в ключе – UserType, объекты UserType должны сравниваться по значению).
M>Дополнительно: Создайте потокобезопасную реализацию этой коллекции (не использовать коллекции из пространства имён System.Collections.Concurrent).
M>


2ГИС детектед . Тут generic конечно был нужен.
Могу показать код для этой задачи который они приняли
Re[4]: тестовое задание
От: alzt  
Дата: 06.12.13 10:36
Оценка:
Здравствуйте, mig84, Вы писали:

Х>>Охм, посмотрел GetElementById и GetElementByName — зачем там dynamic???


M>А почему бы и нет? ))) Просто поменять на MyElement забыл.

Там ретурна ещё нет. Можно добавить ещё myFavouritVar, которую не инициализировать, но от этого код станет только хуже.
Re[7]: тестовое задание
От: alzt  
Дата: 06.12.13 10:39
Оценка:
Здравствуйте, Mystic, Вы писали:

M>
M>public IEnumerable<MyElement> GetElementById(UserType _id)
M>


M>познания в C# не позволяет мне указать произвольный контейнер, куда будут вставлены элементы типа MyElement.


Скорее всего нужен был ещё метод, который ищет по MyId.
Re[2]: тестовое задание
От: alzt  
Дата: 06.12.13 10:41
Оценка: +1
Здравствуйте, samius, Вы писали:

тоже про equals напишу.

public override bool Equals(object obj)
{
    if (!(obj is MyElement))
    {
        MyElement el = (MyElement)obj;
        return Id == el.Id && Name == el.Name;
    }
    else
    {
        return false;
    }
}

Может я совсем C# уже забыл, но что вернёт obj is MyElement если obj имеет тип MyElement?
mig84, ты код запускал хоть раз?
Re[8]: тестовое задание
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 06.12.13 10:54
Оценка:
Здравствуйте, alzt, Вы писали:

A>Скорее всего нужен был ещё метод, который ищет по MyId.


А еще возможен вариант проверки коммуникативных навыков, задание в общем-то составлено витиевато, посему вполне могли проверять, насколько соискатель будет уточнять задание.
Re[9]: тестовое задание
От: alzt  
Дата: 06.12.13 11:32
Оценка:
Здравствуйте, Mystic, Вы писали:

A>>Скорее всего нужен был ещё метод, который ищет по MyId.


M>А еще возможен вариант проверки коммуникативных навыков, задание в общем-то составлено витиевато, посему вполне могли проверять, насколько соискатель будет уточнять задание.


Это вряд ли. Людям ответить лень, а уж что-то уточнять и тем более.
Re[2]: тестовое задание
От: IncremenTop  
Дата: 06.12.13 11:35
Оценка:
Здравствуйте, dasha19, Вы писали:

D>о боже, это полный дотнет головного мозга


Это жуниор или задание выполненное после трудного рабочего дня за 5 минут. Причем здесь платформа?
Re: тестовое задание
От: Sharov Россия  
Дата: 06.12.13 11:39
Оценка:
Здравствуйте, mig84, Вы писали:

В качестве правила хорошего тона (собственно и кода), предостваили
бы за одно и юнит-тесты для Вашего кода. Уже был бы неплохой плюс к карме.
Да и сами тесты помогли бы Вам лучше понять код и требования.
Кодом людям нужно помогать!
Re[2]: тестовое задание
От: Vzhyk  
Дата: 06.12.13 11:54
Оценка:
12/6/2013 2:39 PM, Sharov пишет:

> В качестве правила хорошего тона (собственно и кода), предостваили

> бы за одно и юнит-тесты для Вашего кода. Уже был бы неплохой плюс к карме.
> Да и сами тесты помогли бы Вам лучше понять код и требования.
Так это ты задачку давал? А что ж человеку не ответил, а отвечаешь
только здесь?
Posted via RSDN NNTP Server 2.1 beta
Re[3]: тестовое задание
От: Sharov Россия  
Дата: 06.12.13 12:05
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>Так это ты задачку давал? А что ж человеку не ответил, а отвечаешь

V>только здесь?

как всегда, мимо
Кодом людям нужно помогать!
Re[4]: тестовое задание
От: Vzhyk  
Дата: 06.12.13 12:07
Оценка:
12/6/2013 3:05 PM, Sharov пишет:

> как всегда, мимо

А откуда ты тогда знаешь, что от ТС хотели?
Posted via RSDN NNTP Server 2.1 beta
Re[5]: тестовое задание
От: Sharov Россия  
Дата: 06.12.13 12:09
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>А откуда ты тогда знаешь, что от ТС хотели?


ТС привел описание задачи, Ваш КО.
Кодом людям нужно помогать!
Re[6]: тестовое задание
От: Vzhyk  
Дата: 06.12.13 12:12
Оценка:
12/6/2013 3:09 PM, Sharov пишет:

> ТС привел описание задачи, Ваш КО.

И где там про юнит-тесты?
Posted via RSDN NNTP Server 2.1 beta
Re[7]: тестовое задание
От: Sharov Россия  
Дата: 06.12.13 12:21
Оценка: -1
Здравствуйте, Vzhyk, Вы писали:

V>И где там про юнит-тесты?


А нигде, но вообще говоря было очень грамотно их предоставить.
Т.е. сразу видно, что человек подошел к задаче грамотно, капитально.
Представьте ситуацию: нужно выбрать из двух претендентов, которые с правились с
задачей на ура, т.е. код удовлетворяет всем условиям, но у одно есть юнит-тесты, а
у другого нет. И тут можно склонить чашу весов в свою пользу.
Я не фанат юнит-тестов, сам их редко пишу (считай не пишу вовсе),
но для собеседования уж постарался бы.
Кодом людям нужно помогать!
Re[8]: тестовое задание
От: Vzhyk  
Дата: 06.12.13 12:42
Оценка:
12/6/2013 3:21 PM, Sharov пишет:

> Т.е. сразу видно, что человек подошел к задаче грамотно, капитально.

> Представьте ситуацию: нужно выбрать из двух претендентов, которые с
> правились с
> задачей на ура, т.е. код удовлетворяет всем условиям, но у одно есть
> юнит-тесты, а
> у другого нет. И тут можно склонить чашу весов в свою пользу.
А еще может быть куча нюансов, почему один подошел, а другой нет. Другой
мог быть банально грамотнее, банально дешевле и т.д. и всякие UT могли
не иметь никакого отношения. А вообще можно сказать и так, человек
зачем-то начал делать то, что не просили, нафига, нужен ли нам такой
"инициативный".
Из обсуждения здесь уже видно, что ТС не очень крутой программист на
фоне некоторых местных (я в С# ничего не знаю и посему доверяю местным
знающим) и вполне возможно, что он не подошел по квалификации. Но, это
простейшая культура и на минимальном уровне, если человек сделал задание
и прислал, ответить ему, даже стандартной фразой (по крайней мере я так
понял пост ТС).

З.Ы. А вообще, насчет тестовых заданий. Я их противник, кроме случая,
давать их выпускнику вуза, если у того нет опыта работы на програмерской
конторе.
З.З.Ы. Помню, сделал одним тестовое задание, прошел, конечно и даже 2
месяца поработал и сделал ноги оттуда. С таким говенным кодом и
настолько же убогой организацией разработки мне не приходилось ни до ни
после работать. Ну и еще обычно самые говенные конторы тестовые задания
просят, но этим говоришь досвидания сразу же. Одни вообще ругаться по
телефону стали (да, встречаются и такие), когда я сказал, что мне
выполнять их тестовое задание не интересно.
Posted via RSDN NNTP Server 2.1 beta
Re[9]: тестовое задание
От: Sharov Россия  
Дата: 06.12.13 12:55
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>Но, это

V>простейшая культура и на минимальном уровне, если человек сделал задание
V>и прислал, ответить ему, даже стандартной фразой (по крайней мере я так
V>понял пост ТС).

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

V>З.Ы. А вообще, насчет тестовых заданий. Я их противник, кроме случая,

V>давать их выпускнику вуза, если у того нет опыта работы на програмерской
V>конторе.

Ага, по объявлению людей набирать.
Кодом людям нужно помогать!
Re[2]: тестовое задание
От: namespace  
Дата: 06.12.13 13:33
Оценка: +1
S>Да и сами тесты помогли бы Вам лучше понять код и требования.
Поддерживаю, я бы еще написал сравнительные нагрузочные тесты.
Без тестов самому не понятно, делает ли оно то, что ожидается.
Уж если взялся, то писать как для себя.

Хотя, сам бы стал делать задание, только если бы очень хотелось именно в эту кантору.
Re[7]: тестовое задание
От: robin_of_the_wood Россия  
Дата: 06.12.13 13:49
Оценка:
Здравствуйте, Vzhyk, Вы писали:

>> ТС привел описание задачи, Ваш КО.

V>И где там про юнит-тесты?

Ну про юнит тесты действительно явно сказано не было.
Но вот эта строчка

M>Программа должна содержать пример использования коллекции с идентификатором ключа в виде пользовательского типа (т.е. Id в ключе – UserType, объекты UserType должны сравниваться по значению).


однозначно содержит требование написать не только коллекцию, но и код ее использующий.
А уже UT это будет или main совсем не важно.
И именно в этом коде должен появиться UserType как параметр(может в # используется другой термин но смысл я думаю понятен) обобщенной коллекции.
А у ТС UserType — это тип поля в MyId, а MyId используется внутри коллекции.
В общем все это больше похоже на фэйк или загадку типа "кто найдет больше несоответствий условиям задачи"
Проектирование велосипедов для слепых жирафов
Re: тестовое задание
От: mig84 Россия  
Дата: 06.12.13 15:13
Оценка: 10 (1)
Большое спасибо всем за уделенное этой задаче время.
Действительно куча ошибок. Наверное и правда, дело в том, что после тяжелого рабочего дня и недели в целом.
По сути главная проблема — неверная трактовка задания как такого, ну и отсутствие code review за самим собой, так как делал достаточно быстро.
Отдельное спасибо Хэлкар,Vzhyk,mogikanin,Ромашка.

Кстати, в sln был включен проект с UT. Понятно, что так как условие задачи было воспринято мной неверно, то и тесты некорректны.
В общем, еще раз всем спасибо.
На этом тему можно считать закрытой.

        /// <summary>
        /// Проверяем возможность заполнить коллекцию
        /// </summary>
        [TestMethod]
        public void TestMethod1()
        {
            #region Fake
            MyCollection<MyId, MyElement> collection = new MyCollection<MyId, MyElement>();
            for (int i = 1; i < 10; i++)
            {
                MyElement el = new MyElement()
                {
                    Id = new UserType() { Content = i },
                    Name = String.Format("Unit - {0}", i)
                };
                MyId mid = new MyId(el);
                collection.Add(mid, el);
            }
            #endregion
            Assert.AreEqual(9, collection.Count);

        }

        /// <summary>
        /// Проверяем реакцию на вставку дубликата
        /// </summary>
        [TestMethod]
        public void TestMethod2()
        {
            #region Fake
            MyCollection<MyId, MyElement> collection = new MyCollection<MyId, MyElement>();
            for (int i = 1; i < 10; i++)
            {
                MyElement el = new MyElement()
                {
                    Id = new UserType() { Content = i },
                    Name = String.Format("Unit - {0}", i)
                };
                MyId mid = new MyId(el);
                collection.Add(mid, el);
            }
            #endregion

            MyElement newElement = new MyElement()
                {
                    Id = new UserType() { Content = 1 },
                    Name = String.Format("Unit - {0}", 1 )
                };
            int initCount = collection.Count;
            collection.Add(new MyId(newElement), newElement);
            Assert.AreEqual(initCount, collection.Count);
            
            

        
        }

        /// <summary>
        /// Проверяем работает ли поиск по Id
        /// </summary>
        [TestMethod]
        public void TestMethod3()
        {
            #region Fake
            MyCollection<MyId, MyElement> collection = new MyCollection<MyId, MyElement>();
            for (int i = 1; i < 10; i++)
            {
                MyElement el = new MyElement()
                {
                    Id = new UserType() { Content = i },
                    Name = String.Format("Unit - {0}", i)
                };
                MyId mid = new MyId(el);
                collection.Add(mid, el);
            }
            #endregion

            MyElement lostAndFound = collection.GetElementById(new UserType() { Content=5 });

            Assert.AreNotEqual(null, lostAndFound);

        }

        /// <summary>
        /// Проверяем работает ли поиск по Name
        /// </summary>
        [TestMethod]
        public void TestMethod4()
        {
            #region Fake
            MyCollection<MyId, MyElement> collection = new MyCollection<MyId, MyElement>();
            for (int i = 1; i < 10; i++)
            {
                MyElement el = new MyElement()
                {
                    Id = new UserType() { Content = i },
                    Name = String.Format("Unit - {0}", i)
                };
                MyId mid = new MyId(el);
                collection.Add(mid, el);
            }
            #endregion

            MyElement lostAndFound = collection.GetElementByName("Unit - 7");

            Assert.AreNotEqual(null, lostAndFound);

        }

        /// <summary>
        /// Проверяем работает ли поиск по id или name
        /// </summary>
        [TestMethod]
        public void TestMethod5()
        {
            #region Fake
            MyCollection<MyId, MyElement> collection = new MyCollection<MyId, MyElement>();
            for (int i = 1; i < 10; i++)
            {
                MyElement el = new MyElement()
                {
                    Id = new UserType() { Content = i },
                    Name = String.Format("Unit - {0}", i)
                };
                MyId mid = new MyId(el);
                collection.Add(mid, el);
            }
            #endregion
            
            MyElement lostAndFound = collection.GetElementByIdOrName("Unit - 5");
            Assert.AreNotEqual(null, lostAndFound);

        }

        /// <summary>
        /// Потокобезопасность - проверка одновременной вставки
        /// </summary>
        [TestMethod]
        public void TestMethod6()
        {
            #region Fake
            MyCollection<MyId, MyElement> collection = new MyCollection<MyId, MyElement>();
            for (int i = 1; i < 10; i++)
            {
                MyElement el = new MyElement()
                {
                    Id = new UserType() { Content = i },
                    Name = String.Format("Unit - {0}", i)
                };
                MyId mid = new MyId(el);
                collection.Add(mid, el);
            }
            #endregion

            MyElement newElement = new MyElement()
                {
                    Id = new UserType() { Content = 10 },
                    Name = String.Format("Unit - {0}", 10 )
                };
            int initCount = collection.Count;
            Action<object> action = (object obj) =>
            {
                collection.Add(new MyId(newElement), newElement);
            };

            t.Task t1 = new t.Task(action,"thread1");
            t.Task t2 = new t.Task(action, "thread2");
            t.Task t3 = new t.Task(action, "thread3");

            t1.Start();
            t2.Start();
            t3.Start();

            t1.Wait();
            t2.Wait();
            t3.Wait();

            Assert.AreEqual(initCount + 1, collection.Count);
        
        }
Re[2]: тестовое задание
От: mig84 Россия  
Дата: 06.12.13 15:23
Оценка:
Не было просто серьезной мотивации для решения более серьезного, если честно.
Так как делалось все довольно быстро — то куда ж без хаоса.
На счет не выполняется — это Вы зря. Я же только описание классов привел.
На счет последнего вопроса — да. А Вы? Никогда не доводилось писать быстро? Или даже в таких случаях у Вас все идеально? )))


N>Полкода лишние и он не делает то, что должен. Даже близко. Много очевидных опечаток. Общий хаос в коде.

N>Рекомендую внимательнее прочесть задание и сделать значительно больше усилий над разработкой.
N>А вы уже работали программистом?
Re[2]: тестовое задание
От: mig84 Россия  
Дата: 06.12.13 15:28
Оценка:
Они самые Если возможно, то поделитесь — любопытно.


J>2ГИС детектед . Тут generic конечно был нужен.

J>Могу показать код для этой задачи который они приняли
Re: тестовое задание
От: nen777w  
Дата: 06.12.13 21:13
Оценка:
M>Этот вариант решения, как видно, не понравился проверявшему.
M>Буду признателен, если "ткнете носом" в ошибки. Понимаю, что, возможно подошел к решению довольно формально, но по требованиям вроде все реализовал. Или чего-то не так понял.

Забей, вот мой случай
Автор: nen777w
Дата: 15.03.13
, чего они отказали я до сиих пор ХЗ.
Но судя по коментраиям бывшего инсайдера оно и к лучшему.
Если интересно ссылка на выполнение задание
тут
Re[3]: тестовое задание
От: alzt  
Дата: 09.12.13 07:37
Оценка: +1
Здравствуйте, mig84, Вы писали:

M>Не было просто серьезной мотивации для решения более серьезного, если честно.

M>Так как делалось все довольно быстро — то куда ж без хаоса.

Здесь проглядываются довольно простые ошибки, которые опечатками не объяснишь. Код слабоват.

M>На счет последнего вопроса — да. А Вы? Никогда не доводилось писать быстро? Или даже в таких случаях у Вас все идеально? )))


А зачем тогда было отправлять? Если неохота тратить своё время, то лучше не делать тестовое задание. Но взяться делать и при этом вполсилы это как то совсем странно. Либо попадёшь в плохую контору (где требуют тестовые задания несмотря на то, что здесь все стонут, но при этом не проверяют их, либо их устраивает посредственное качество), либо гарантированно потеряешь время.
Re[3]: тестовое задание
От: Философ Ад http://vk.com/id10256428
Дата: 09.12.13 17:34
Оценка:
Здравствуйте, alzt, Вы писали:

A>Здравствуйте, samius, Вы писали:


A>тоже про equals напишу.


A>
A>public override bool Equals(object obj)
A>{
A>    if (!(obj is MyElement))
A>    {
A>        MyElement el = (MyElement)obj; //NULL
A>        return Id == el.Id && Name == el.Name; //БАБАХ new NullReferenceException();
A>    }
A>


Добавл комменты.

A>Может я совсем C# уже забыл, но что вернёт obj is MyElement если obj имеет тип MyElement?


Ты ничего не забыл.
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Всё сказанное выше — личное мнение, если не указано обратное.
Re[2]: тестовое задание
От: Философ Ад http://vk.com/id10256428
Дата: 09.12.13 17:34
Оценка:
Здравствуйте, dasha19, Вы писали:

D>о боже, это полный дотнет головного мозга


нет, это слабенький джуниор
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: тестовое задание
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.12.13 18:11
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>Здравствуйте, alzt, Вы писали:


A>>
A>>public override bool Equals(object obj)
A>>{
A>>    if (!(obj is MyElement))
A>>    {
A>>        MyElement el = (MyElement)obj; //NULL
A>>        return Id == el.Id && Name == el.Name; //БАБАХ new NullReferenceException();
A>>    }
A>>


Ф>Добавл комменты.

По-моему они еще больше запутывают. Это для прикола, или это прогнозируемые значения и события?
Re[5]: тестовое задание
От: Философ Ад http://vk.com/id10256428
Дата: 09.12.13 18:49
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Философ, Вы писали:


Ф>>Здравствуйте, alzt, Вы писали:


A>>>
A>>>public override bool Equals(object obj)
A>>>{
A>>>    if (!(obj is MyElement))
A>>>    {
A>>>        MyElement el = (MyElement)obj; //NULL
A>>>        return Id == el.Id && Name == el.Name; //БАБАХ new NullReferenceException();
A>>>    }
A>>>


Ф>>Добавл комменты.

S>По-моему они еще больше запутывают. Это для прикола, или это прогнозируемые значения и события?

И первое, и второе.


00 if (!(obj is MyElement)) //условие истинно, если obj не является типом MyElement — восклицательный знак всё портит

10 MyElement el = (MyElement)obj; // в шарпе это вообще не выполнится — вывалится с InvalidCastException. Чтобы выполнилось можно кастовать с помощью оператора as

10 MyElement el = obj as MyElement; //а вот так выполнится, el будет равен NULL

20 return Id == el.Id && Name == el.Name; //оращение к полю неинициализированного объекта вывалит исключение NullReferenceException()
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Всё сказанное выше — личное мнение, если не указано обратное.
Re[6]: тестовое задание
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.12.13 20:05
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>Здравствуйте, samius, Вы писали:


S>>По-моему они еще больше запутывают. Это для прикола, или это прогнозируемые значения и события?


Ф>И первое, и второе.



Ф>00 if (!(obj is MyElement)) //условие истинно, если obj не является типом MyElement — восклицательный знак всё портит


Ф>10 MyElement el = (MyElement)obj; // в шарпе это вообще не выполнится — вывалится с InvalidCastException. Чтобы выполнилось можно кастовать с помощью оператора as

С этим согласен. Но потому как в коде не as, обсуждать остальное смысла нет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.