Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 12:02
Оценка: 14 (2)
Лет 10 пишу в основном на С++ и немного на других языках, C# не пробовал. Предложили работу джуниором на С# честно сказал что его не знаю, но давно думаю освоить. Сказали — мы верим что с вашим опытом вы сможете, напишите тестовое задание, а мы посмотрим. Прочел полкнижки по шарпу, написал задание. Вердикт был в стиле "вы были правы, это написано на с++, а не c#, так что к сожалению не подойдете".

Больше комментариев нет, а мне вот интересно что-же так такого страшного? Если бы дело в том что плохо написал задание, там какие-то проблемы или плохой код — я бы понял, но смущает именно упор на том что это "написано не на С#". Кто-нибудь может показать вкратце где тут проблемы и как надо было правильно делать.

Задание вкратце "Необходимо реализовать блокирующую очередь и автоматические тесты к ней. Задача должна быть выполнена как можно более простым способом. .Net 3.5 or 4.0, + тесты, + отсутствие проблем с многопоточностью, + правильный стиль етс."


Главный класс

using System;
/* 
 * ReadMe
 * 
 * Так как задача должна быть выполнена как можно более простым способом, был реализован класс BegBlockedQueue1<T> 
 * который решает задачу наиболее простым способом.
 * 
 * Класс BegBlockedQueue2<T> это собственная реализация блокирующей очереди, частично совместимой со стандартной ConcurrentQueue<T>
 * опять же, помня про требование простейшего способа, поддерживается только самый просто режим работы - 1 производитель \1 потребитель 
 * BegBlockedQueue2<T> не реализует интерфейс IProducerConsumerCollection<T> для возможного использования с .Net 3.5 (и возможно более ранними версиями, не тестировалось)
 * 
 * Оба класса успешно проходят весь набор тестов.
 * Переключить тестирование между классами BegBlockedQueue1<T> и BegBlockedQueue2<T> можно комментируя\раскоментирую строчку 
 * #define TestBegBlockedQueue1
 * в файле UnitTest.cs
 */

namespace BegBlockedQueue
{
    internal class Program
    {
        private static void Main()
        {
            Test1();
            Test2();
        }


        private static void Test1()
        {
            Console.WriteLine(" --- Start Test1");
            BegBlockedQueue1<int> q = new BegBlockedQueue1<int>();

            q.Add(2);
            q.Add(32);
            q.Add(212);
            q.CompleteAdding();

            Console.WriteLine("count items in collection = {0}", q.Count);

            try
            {
                while (true) Console.WriteLine(q.Take());
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("That's All!");
            }

            Console.WriteLine(" --- End Test1");
        }


        private static void Test2()
        {
            Console.WriteLine(" --- Start Test2");
            BegBlockedQueue2<int> q = new BegBlockedQueue2<int>(5);

            q.Add(66);
            q.Add(67);
            q.Add(68);
            q.CompleteAdding();
            Console.WriteLine("count {0} ({1})", q.Count, q.BoundedCapacity);

            try
            {
                //int t; while (q.TryTake(out t)) Console.WriteLine(t);
                while (true) Console.WriteLine(q.Take());
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("That's All!");
            }

            Console.WriteLine(" --- End Test2");
        }
    }
}


Сама очередь

using System;
using System.Collections.Generic;
using System.Threading;

namespace BegBlockedQueue
{
    ///<remarks> 
    ///  Own realization of blocked queue class, testing in .Net 3.5 and 4.0
    ///  Note: support only single producer/single consumer mode of work
    ///</remarks>
    public class BegBlockedQueue2<T>
    {
        private readonly Queue<T> _data;
        private readonly object _locker = new object();
        private bool _isAddingCompleted = false;
        

        // ------------- Constructors

        /// <summary>
        /// Initializes a new instance of the BegBlockedQueue2 class without an upper-bound.
        /// </summary>
        public BegBlockedQueue2()
        {
            _data = new Queue<T>();
            BoundedCapacity = -1;
        }

        /// <summary>
        /// Initializes a new instance of the BegBlockedQueue2 class with the specified upper-bound.
        /// </summary>
        /// <param name="boundedCapacity"></param>
        public BegBlockedQueue2(int boundedCapacity)
        {
            _data = new Queue<T>(boundedCapacity);
            BoundedCapacity = boundedCapacity;
        }


        // ------------- Properties

        /// <summary>
        /// Gets the number of elements contained in the BegBlockedQueue2.
        /// </summary>
        public int Count
        {
            get { return _data.Count; }
        }

        /// <summary>
        /// Gets whether this BegBlockedQueue2 has been marked as complete for adding.
        /// </summary>
        public bool IsAddingCompleted
        {
            get { return _isAddingCompleted; }
            protected set { _isAddingCompleted = value; }
        }

        /// <summary>
        /// Gets whether this BegBlockedQueue2 has been marked as complete for adding and is empty.
        /// </summary>
        public bool IsCompleted
        {
            get { return _isAddingCompleted && Count == 0; }
        }

        /// <summary>
        /// Gets the bounded capacity of this BegBlockedQueue2 instance
        /// </summary>
        public int BoundedCapacity { get; protected set; }


        // ------------- Methods

        /// <summary>
        /// Marks the BegBlockedQueue2 instances as not accepting any more additions.
        /// </summary>
        public void CompleteAdding()
        {
            lock (_locker)
            {
                IsAddingCompleted = true;

                // we should notice consumer thead if it waiting for adding new item inside Take()
                Monitor.Pulse(_locker);
            }
        }

        /// <summary>
        /// Try to add the item to to BegBlockedQueue2, 
        /// </summary>
        /// <param name="item">The item to be added to the collection.</param>
        /// <exception cref="InvalidOperationException"></exception>
        /// <returns>True if item was added to collection, otherwise false.</returns>
        public bool TryAdd(T item)
        {
            if (IsAddingCompleted)
                throw new InvalidOperationException("The collection has been marked as complete with regards to additions.");

            lock (_locker)
            {
                if (BoundedCapacity != -1 && Count >= BoundedCapacity)
                    return false;

                _data.Enqueue(item);

                // Maybe there is waiting consumer inside Take
                if (Count == 1)
                    Monitor.Pulse(_locker);

                return true;
            }
        }


        /// <summary>
        /// Add the item to to BegBlockedQueue2, may block producer until space is available to store the provided item.
        /// </summary>
        /// <param name="item">The item to be added to the collection.</param>
        /// <exception cref="InvalidOperationException"></exception>
        public void Add(T item)
        {
            lock (_locker)
            {
                while (TryAdd(item) == false)
                    Monitor.Wait(_locker);
            }
        }

        /// <summary>
        /// Tries to remove an item from the BegBlockedQueue2.
        /// </summary>
        /// <param name="item">The item to be removed from the collection.</param>
        /// <returns>true if an item could be removed; otherwise, false.</returns>
        public bool TryTake(out T item)
        {
            lock (_locker)
            {
                if (Count == 0)
                {
                    item = default(T);
                    return false;
                }

                item = _data.Dequeue();

                // Maybe there is waiting producer inside Add
                if (IsAddingCompleted == false && Count == BoundedCapacity - 1)
                    Monitor.Pulse(_locker);

                return true;
            }
        }


        /// <summary>
        /// Removes an item from the BegBlockedQueue2.
        /// </summary>
        /// <returns>The item removed from the collection..</returns>
        public T Take()
        {
            lock (_locker)
            {
                T item;
                while (TryTake(out item) == false)
                {
                    if (IsCompleted)
                        throw new InvalidOperationException();

                    Monitor.Wait(_locker);
                }

                return item;
            }
        }
    }
}


Тесты


// Use this for switching between BegBlockedQueue1 and BegBlockedQueue2
// if this line is commented  BegBlockedQueue2 will be used for testing instead of BegBlockedQueue1
//#define TestBegBlockedQueue1

using System;
using System.Reflection;
using System.Threading;
using NUnit.Framework;
using BegBlockedQueue;

namespace UnitTest
{
#if TestBegBlockedQueue1
    using TestClassImplementation = BegBlockedQueue1<int>;
#else
    using TestClassImplementation = BegBlockedQueue2<int>;
#endif

    [TestFixture]
    public class TestClass
    {
        private TestClassImplementation _to;
        private Random _rnd;
        private int _maxCountDataInThreadTest = 1000;
        private int _countAddedDataInThreadTest;
        private int _countTakenDataInThreadTest;

        // ---------

        [TestFixtureSetUp]
        public void TestSetup()
        {
            _to = new TestClassImplementation();
            _rnd = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
        }

        [TearDown]
        public void FinalizeTest()
        {
            _to = new TestClassImplementation();
        }


        // ---------


        [Test]
        public void TryAddFewItems()
        {
            Console.WriteLine("Start test - {0}", MethodBase.GetCurrentMethod().Name);

            // --- recreate queue with upper-bound limit
            _to = new TestClassImplementation(10);

            // --- TryAdd a few items
            Assert.AreEqual(_to.Count, 0);
            Assert.AreEqual(_to.BoundedCapacity, 10);

            _to.TryAdd(_rnd.Next());
            Assert.AreEqual(_to.Count, 1);

            for (int t = 0; t < 20; ++t)
                _to.TryAdd(_rnd.Next());

            Assert.AreEqual(_to.Count, _to.BoundedCapacity);

            Console.WriteLine("Really added {0} items", _to.BoundedCapacity);
            Console.WriteLine("End test - {0}", MethodBase.GetCurrentMethod().Name);
        }


        [Test]
        public void TryTakeFewItems()
        {
            int item;
            Assert.AreEqual(_to.Count, 0);
            Assert.AreEqual(_to.TryTake(out item), false);

            int[] array = new int[20];

            for (int t = 0; t < 20; ++t)
            {
                array[t] = _rnd.Next();
                _to.TryAdd(array[t]);
                Console.WriteLine("Added {0}", array[t]);
            }

            for (int t = 0; t < 20; ++t)
            {
                Assert.AreEqual(_to.TryTake(out item), true);
                Assert.AreEqual(item, array[t]);
                Console.WriteLine("    Taken {0}", item);
            }

            Assert.AreEqual(_to.TryTake(out item), false);
            Assert.AreEqual(item, default(int));
        }

        [Test]
        public void TestIsCompleted()
        {
            Assert.AreEqual(_to.IsAddingCompleted, false);
            Assert.AreEqual(_to.IsCompleted, false);

            Assert.AreEqual(_to.TryAdd(0), true);
            _to.CompleteAdding();
            Assert.AreEqual(_to.IsAddingCompleted, true);
            Assert.AreEqual(_to.IsCompleted, false);

            try
            {
                _to.TryAdd(0);
                Assert.Fail();
            }
            catch (InvalidOperationException)
            {
            }

            int item;
            Assert.AreEqual(_to.TryTake(out item), true);
            Assert.AreEqual(_to.IsAddingCompleted, true);
            Assert.AreEqual(_to.IsCompleted, true);
        }


        [Test]
        public void AddFewItems()
        {
            Console.WriteLine("Start test - {0}", MethodBase.GetCurrentMethod().Name);

            // --- Add a few items
            Assert.AreEqual(_to.Count, 0);
            _to.Add(_rnd.Next());
            Assert.AreEqual(_to.Count, 1);

            int count = _rnd.Next(50000);
            for (int t = 0; t < count; ++t)
                _to.Add(_rnd.Next());
            _to.CompleteAdding();

            Console.WriteLine("Added {0} items", count + 1);

            Assert.AreEqual(_to.Count, count + 1);

            Console.WriteLine("End test - {0}", MethodBase.GetCurrentMethod().Name);
        }


        [Test]
        public void AddAndGetFewItems()
        {
            Console.WriteLine("Start test - {0}", MethodBase.GetCurrentMethod().Name);

            // --- Add a few items
            int count = _rnd.Next(50000);
            for (int t = 0; t < count; ++t)
                _to.Add(_rnd.Next());
            _to.CompleteAdding();

            // --- read back some items
            int countTaked = _rnd.Next(count);
            for (int t = 0; t < countTaked; ++t)
                _to.Take();

            Console.WriteLine("Added {0} items, taked {1}, still in queue {2} (really {3})", count, countTaked,
                              count - countTaked, _to.Count);
            Assert.AreEqual(_to.Count, count - countTaked);

            // --- read all items
            if (_to.Count > 0)
            {
                while (_to.Count > 0)
                    _to.Take();
            }
            Assert.AreEqual(_to.Count, 0);

            Console.WriteLine("End test - {0}", MethodBase.GetCurrentMethod().Name);
        }

        // ----- Test with threads
        private void AddInThread(object data)
        {
            _countAddedDataInThreadTest = _rnd.Next(_maxCountDataInThreadTest/2, _maxCountDataInThreadTest);
            for (int t = 0; t < _countAddedDataInThreadTest; ++t)
            {
                int i = _rnd.Next(1000);
                _to.Add(i);
                Console.WriteLine("Added {0}", i);
                if ((int)data > 0) Thread.Sleep((int)data);
            }

            _to.CompleteAdding();
        }

        private void TakeInThread(object data)
        {
            try
            {
                while (true)
                {
                    if ((int)data > 0) Thread.Sleep((int)data);
                    int i = _to.Take();
                    Console.WriteLine("    Taken {0}", i);
                    ++_countTakenDataInThreadTest;
                }
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Taked all data");
            }
        }

        [Test]
        public void TestInThreads()
        {
            // --- recreate queue with upper-bound limit
            _to = new TestClassImplementation(10);

            _countAddedDataInThreadTest = _countTakenDataInThreadTest = 0;
            Thread tAdd = new Thread(AddInThread);
            tAdd.Start(0);
            Thread tTake = new Thread(TakeInThread);
            tTake.Start(0);

            tAdd.Join();
            tTake.Join();

            Console.WriteLine("TestInThread: added {0}, taken {1} items", _countAddedDataInThreadTest, _countTakenDataInThreadTest);
            Assert.AreEqual(_countAddedDataInThreadTest, _countTakenDataInThreadTest);
        }

        [Test]
        public void TestInThreadsForceProducerBlock()
        {
            // --- recreate queue with upper-bound limit
            _to = new TestClassImplementation(5);
            _maxCountDataInThreadTest = 50;

            _countAddedDataInThreadTest = _countTakenDataInThreadTest = 0;
            Thread tAdd = new Thread(AddInThread);
            tAdd.Start(0);
            Thread tTake = new Thread(TakeInThread);
            tTake.Start(200);

            tAdd.Join();
            tTake.Join();

            Console.WriteLine("TestInThread: added {0}, taken {1} items", _countAddedDataInThreadTest, _countTakenDataInThreadTest);
            Assert.AreEqual(_countAddedDataInThreadTest, _countTakenDataInThreadTest);
        }

        [Test]
        public void TestInThreadsForceConsumerBlock()
        {
            // --- recreate queue with upper-bound limit
            _to = new TestClassImplementation(5);
            _maxCountDataInThreadTest = 50;

            _countAddedDataInThreadTest = _countTakenDataInThreadTest = 0;
            Thread tTake = new Thread(TakeInThread);
            tTake.Start(0);
            Thread tAdd = new Thread(AddInThread);
            tAdd.Start(200);

            tAdd.Join();
            tTake.Join();

            Console.WriteLine("TestInThread: added {0}, taken {1} items", _countAddedDataInThreadTest, _countTakenDataInThreadTest);
            Assert.AreEqual(_countAddedDataInThreadTest, _countTakenDataInThreadTest);
        }
    }
}


Из того что я вижу тут не try C#, это неиспользование var для локальных переменных, а явное указание типа. Решарпер настойчиво предлагал их использовать, но я не согласился. Что еще тут не так?

p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.
--
Блог шароварщика ::Микроблог про wxWidgets
Re: Уши C++ или C++ style vs C# style
От: Visor2004  
Дата: 29.08.12 12:16
Оценка: :)
Здравствуйте, Begemot_, Вы писали:


B_>Из того что я вижу тут не try C#, это неиспользование var для локальных переменных, а явное указание типа. Решарпер настойчиво предлагал их использовать, но я не согласился. Что еще тут не так?

B_>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.

Префиксы у полей, ну и комментарии отделяющие блоки кода, с C# для этого есть регионы, а так вроде все норм. Имхо, к вам придрались просто по пустяку.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re: Уши C++ или C++ style vs C# style
От: Visor2004  
Дата: 29.08.12 12:26
Оценка:
Здравствуйте, Begemot_, Вы писали:

В догонку можете почитать вот это Design Guidelines for Class Library Developers. Правда, не смотря на наличие этого документа, большая часть девелоперов, которых я видел, все равно продолжают считать себя самыми умными и коверкают названия префиксами и постфиксами как хотят. Могу поспорить, что в той пафосной конторке, в которую вы собеседовались имена полей начинаются с какого-нить префикса.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 12:34
Оценка:
Да, нет со стандартом кодирования там вроде все разумно, в тестовом задании было сказано придерживаться этого http://www.rsdn.ru/article/mag/200401/codestyle.XML
Что я и пытался делать, а что подразумевается под "Префиксы у полей"? они у меня неправильными вроде старался сделать как указано.
--
Блог шароварщика ::Микроблог про wxWidgets
Re: Уши C++ или C++ style vs C# style
От: Sinix  
Дата: 29.08.12 12:34
Оценка: +2
B_>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.

Не знаю. На мой взгляд всё вполне читаемо, с учётом того, что ты только перешёл на c# — так вообще зашибись
Re[3]: Уши C++ или C++ style vs C# style
От: Visor2004  
Дата: 29.08.12 12:46
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>что подразумевается под "Префиксы у полей"?

подразумевается буквально префиксы у полей, у вас каждое поле начинается со знака подчеркивания, что не рекомендуется делать микрософтом.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re: Уши C++ или C++ style vs C# style
От: GGoga  
Дата: 29.08.12 12:48
Оценка: +2
Здравствуйте, Begemot_, Вы писали:

B_>Лет 10 пишу в основном на С++ и немного на других языках, C# не пробовал. Предложили работу джуниором на С# честно сказал что его не знаю, но давно думаю освоить. Сказали — мы верим что с вашим опытом вы сможете, напишите тестовое задание, а мы посмотрим. Прочел полкнижки по шарпу, написал задание. Вердикт был в стиле "вы были правы, это написано на с++, а не c#, так что к сожалению не подойдете".

B_>Больше комментариев нет, а мне вот интересно что-же так такого страшного? Если бы дело в том что плохо написал задание, там какие-то проблемы или плохой код — я бы понял, но смущает именно упор на том что это "написано не на С#". Кто-нибудь может показать вкратце где тут проблемы и как надо было правильно делать.
B_>Задание вкратце "Необходимо реализовать блокирующую очередь и автоматические тесты к ней. Задача должна быть выполнена как можно более простым способом. .Net 3.5 or 4.0, + тесты, + отсутствие проблем с многопоточностью, + правильный стиль етс."

B_>...


B_>Из того что я вижу тут не try C#, это неиспользование var для локальных переменных, а явное указание типа. Решарпер настойчиво предлагал их использовать, но я не согласился. Что еще тут не так?


B_>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.


1) Еще раз убеждаюсь во "вреде" тестовых заданий.
2) Еще раз убеждаюсь в том, что конторы, их дающие надо обходить 10-й дорогой.

ИМХО, код (его стилистика) вполне читаем и хорошо оформлен (логику не смотрел). То, что Вам отказали — скорее плюс, чем минус, потому как см. пункты выше. Когда я шел на вторую работу, я шарпа не знал вообще, а брали именно на шарписта. На собеседовании спрашивали по ООП и не давали никаких тестовых заданий. Думаю, что если у Вас опыт в РЕАЛЬНЫХ 10 лет, то контора сама себе злобная буратино, что отказала за непонятные притянутые за уши причины. С таким опытом и прочитанным Рихтером (по шарпу) Вам можно смело идти мидлом и через минимальное время (когда тонкости языка и фреймворка будут изучены) становится синьйором.

Удачи!
Re[2]: Уши C++ или C++ style vs C# style
От: Vaako Украина  
Дата: 29.08.12 13:07
Оценка:
Здравствуйте, Sinix, Вы писали:


B_>>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.


S>Не знаю. На мой взгляд всё вполне читаемо, с учётом того, что ты только перешёл на c# — так вообще зашибись


Видели бы вы мою первую прогу на С#
Помоему нормально.
Re[2]: Уши C++ или C++ style vs C# style
От: vmpire Россия  
Дата: 29.08.12 13:12
Оценка:
Здравствуйте, GGoga, Вы писали:

GG>1) Еще раз убеждаюсь во "вреде" тестовых заданий.

GG>2) Еще раз убеждаюсь в том, что конторы, их дающие надо обходить 10-й дорогой.

Вот с этим утверждением я бы поспорил.
Наша контора несколько лет назад отказалась от тестовых заданий, о чём я давно жалею.
Тестовым заданием на раз отсекаются пионеры-теоретики, которые где-то что-то слышали, но как применять не знают. В конце концов, человек-то берётся код писать, а не про ООП рассказывать. Рассказывать-то мнегие мастера.

Я бы тестовое задание давал. И сам я такие делал, когда искад работу.
Конечно, тестовое задание не должно быть на какие-то специальные знания, только если эти знания составляют обязательные требования.
Но вот когда человек, декларирующий хорошее знание SQL не может в уме вычислить результаты простого држойна — это настораживает.

К слову, топикстартера с таким кодом я бы взял, причём даже не на джуниора.
Re[3]: Уши C++ или C++ style vs C# style
От: GGoga  
Дата: 29.08.12 13:29
Оценка: 15 (4) +8 -1
Здравствуйте, vmpire, Вы писали:

V>Вот с этим утверждением я бы поспорил.

V>Наша контора несколько лет назад отказалась от тестовых заданий, о чём я давно жалею.
V>Тестовым заданием на раз отсекаются пионеры-теоретики, которые где-то что-то слышали, но как применять не знают. В конце концов, человек-то берётся код писать, а не про ООП рассказывать. Рассказывать-то мнегие мастера.

V>Я бы тестовое задание давал. И сам я такие делал, когда искад работу.

V>Конечно, тестовое задание не должно быть на какие-то специальные знания, только если эти знания составляют обязательные требования.
V>Но вот когда человек, декларирующий хорошее знание SQL не может в уме вычислить результаты простого држойна — это настораживает.

Ок, тогда могу ли я, в ответ на просьбу о написании тестового задания, попросить аванс, чтобы проверить платежеспособность работодателя? Да на такой вопрос работодатель "обезумеет от наглости" соискателя.

А то получается, что в процессе найма только одна тестируемая сторона — соискатель. А то, что работодатель может быть "г...ном" всегда умалчивается.
Куча фирм ищут сотрудников без тестовых заданий и как-то себе выживают и даже деньги зарабатывают. Т.е. получается, что им удается отсеивать плохих кандидатов.
Мне лично все равно, кто и как относится к тестовым заданиям. Я просто даже не пойду на собеседование в фирму, которая просит выполнить такое задание (да, фирмы мечты у меня нет, а на нынешнем рынке труда многие платят одинаковые деньги), потому что под "всего лишь 2 часами потраченного времени" прячется 2 реальных дня, потому что если напишешь за те же 2 часа получишь — "вот здесь можно было бы написать так, сделать еще то-то и то-то, да дописать такое-то", спросив, что этого не было в требованиях — "ну это само по себе подразумевалось..." — занавес...
Почитайте данный форум и найдете кучу тем, где кандидат (ТС не исключение) написал тестовое задание, а его не взяли. Он выставил его здесь "напоказ", а оказывается, что и придраться то не к чему, кроме небольшого отступа и открывающейся фигурной скобки на на отдельной строчке.

Все имхо, но мое отношение к тестам — резко отрицательное. Нервы и личное время дороже и можно вполне устроиться без оного.
Re[4]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 13:32
Оценка:
Здравствуйте, Visor2004, Вы писали:

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

Да я знаю что MS этого требования нету, но в том стандарте кодирования что мне дали написано что приватные поля класса должны начинаться с "_", и это кстати, единственное что мне там активно не понравилось Ну и решарпер с настройками по умолчанию тоже требует того же. Мне конечно не понравилось, но что делать сказали надо, значит надо. Тем более что отрефакторить готовый код перед отсылкой не сложно


>К слову, топикстартера с таким кодом я бы взял, причём даже не на джуниора.

Ну у меня тоже есть версия что отказали именно по этому, им вроде нужны джуниоры и когда я сказал что шарпа в глаза не видел — сказали, что ничего страшного, подойду. Видимо код их смутил, не стоило так серьёзно относится к тестовому заданию наверное
--
Блог шароварщика ::Микроблог про wxWidgets
Re[5]: Уши C++ или C++ style vs C# style
От: fddima  
Дата: 29.08.12 13:46
Оценка: +1
Здравствуйте, Begemot_, Вы писали:

B_>Да я знаю что MS этого требования нету, но в том стандарте кодирования что мне дали написано что приватные поля класса должны начинаться с "_", и это кстати, единственное что мне там активно не понравилось Ну и решарпер с настройками по умолчанию тоже требует того же. Мне конечно не понравилось, но что делать сказали надо, значит надо. Тем более что отрефакторить готовый код перед отсылкой не сложно

А StyleCop который в дефолтной конфигурации, который некоторые считают тоже рекомендацией от МС — ещё предлагает любой member access (т.е. поля — методы — пофигу), предворять "this." и "base." соответственно.
Префикс "_" — используют очень многие, и это вполне имеет право на жизнь.
Ну а то, что половина BCL имеет в себе члены m_xxxx — то конечно же это ошибки "молодости", когда .NET/BCL был зелёным а гайдов не было — только почему-то в HashSet<T> — всё те же m_buckets/m_count. В BigInteger (System.Numerics) — префикс s_ на статических полях.
Да и чего уже там — префиксы используются в полный рост, не только для полей:
// System.Numerics.BigInteger
internal int _Sign
{
    get { return this._sign; }
}

Это конечно же всё потому, что МС внутри использует тайный coding guidelines, а народу лапшу на уши вешает.

Единственный разуменый критерий — это выработать (или взять уже готовый) один из подходящих стандартов и его придерживаться внутри команды/проекта. Слепо же следовать рекомендациям от МС не нужно, хотя их гайдлайны обязательны для прочтения и достойны рассмотрения в числе первых.
Re: Уши C++ или C++ style vs C# style
От: Codechanger Россия  
Дата: 29.08.12 13:49
Оценка: 2 (2)
Здравствуйте, Begemot_, Вы писали:


B_>Из того что я вижу тут не try C#, это неиспользование var для локальных переменных, а явное указание типа. Решарпер настойчиво предлагал их использовать, но я не согласился. Что еще тут не так?


B_>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.


1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно
2.Привычка к for.
3.Привычка к ++i, а не i++.
4.Внутри lock вроде дополнительный Monitor.Wait не нужен.
5.Префиксы режут глаз.
6.Названия переменных не слишком говорящие.
7.Смешение автосвойств и свойств с backing field. Сейчас в принципе наблюдается тенденция использовать автосвойства, если не нужна логика выставления/получения значений дополнительная.
8.Выход из вечного цикла по исключению — как-то не очень кошерно. В целом в C# не принято включать throw как стандартную ветку исполнения кода(вопрос дискуссионный).
9.Непонятен смысл метода CompleteAdding().
10.Для многопоточной записи/выборки объектов используется ConcurrentQueue. При ее использовании куча локов уходит.

В целом код неплохой довольно.
Re: Уши C++ или C++ style vs C# style
От: matumba  
Дата: 29.08.12 13:56
Оценка: -9 :))) :))
Здравствуйте, Begemot_, Вы писали:

B_>Вердикт был в стиле "вы были правы, это написано на с++, а не c#, так что к сожалению не подойдете".


Возможно, они и правы — я бы на вашем месте не особо обижался. Это как хоккеиста учить балету — он всё равно будет пытаться скользить по сцене. (и недоумевать: "ну я же двигаюсь!") Увы, в вас "обижаются" амбиции "сипиписника" — мол, я такой крутой перец, ща вам на любом шарпе сбацаю! А тут опустили как второклассника. Забудьте С++ — это не понты, это ООП-мракобесие на ассемблере.

B_> Кто-нибудь может показать вкратце где тут проблемы и как надо было правильно делать.


Если откровенно, то я даже задания не понял Что такое "блокирующая очередь"? Блокирующая кого, от чего и в какое время? Вы уверены, что правильно поняли задание?

B_>... и автоматические тесты к ней.


Могу успокоить только одним: контора, возлагающая надежды на тесты — тухлое сборище дилетантов. Беда в том, что "тесты" как пилочка для ногтей — где-то незаменима, но в большинстве случаев — бесполезная %#$%#$я.

B_>Сама очередь

B_> private readonly Queue<T> _data;

B_> public BegBlockedQueue2()

B_> {
B_> _data = new Queue<T>();
B_> BoundedCapacity = -1;

Вот это капасити — зачем?? Просто возможностей Queue недостаточно?


B_>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.


Да чёрт его знает... у меня код примерно такой же. И подчёркивания для приватных полей тоже юзаю. Просто предположение: вы как-то перемудрили с решением, не поняв задачу. Я даже скроллировать устал, не то, что читать! — возможно, это и послужило каким-то странным намёком на "сипипи головного мозга"
Ещё раз: не обижайтесь, для успешного развития в C# вам придётся начисто забыть C++.
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 14:25
Оценка: 18 (1) +1
Здравствуйте, Codechanger, Вы писали:


Можно я покоментирую\поспорю, исключительно ради истины?

C>1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно

В с++ это как раз не тоже принято. Это я ошибся. Когда читал книжку там написано что в отличии от с++, в шарпе нельзя в логических выражениях использовать равенство нулю\не нулю, а надо явно проверять на значение. То есть вместо if (str.Length), надо писать if (str.Length > 0), мне это не понравилось и я запомнил. А когда писал код, почему-то решил что и bool b = true; if (b); тоже нельзя писать, а надо обязательно if (b = true) использовать. Но это каюсь моя ошибка просто, но не как не уши С++, где повторюсь так не пишут.

C>2.Привычка к for.

Чем это плохо? И какие конкретно for в моем коде надо заменить на другой типа цикла?

C>3.Привычка к ++i, а не i++.

это да, чисто из плюсов, ну это автоматически. В принципе при необходимости за неделю можно переучится.


C>4.Внутри lock вроде дополнительный Monitor.Wait не нужен.

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


C>5.Префиксы режут глаз.

Префиксы (если вы про _ у приватных полей)определены стандартом кодирования, мне тоже не нравятся, но пришлось сделать.


C>6.Названия переменных не слишком говорящие.

хм, чисто субъективно не согласен, мне все говорящие Но это субъективно, но в любом случае не говорит о том что программа написана "на с++, а не на с#" как сказали мне.


C>7.Смешение автосвойств и свойств с backing field. Сейчас в принципе наблюдается тенденция использовать автосвойства, если не нужна логика выставления/получения значений дополнительная.

Ну везде где было можно я использовал автосвойства, там где было нельзя — писал свои. Или стоило отказаться от автосвойств вообще, если я не могу сделать все свойства автоматическими?


C>8.Выход из вечного цикла по исключению — как-то не очень кошерно. В целом в C# не принято включать throw как стандартную ветку исполнения кода(вопрос дискуссионный).

Пример взят прямо из мсдн. При использовании Take() в блокирующей очереди нет другого свойства выйти из цикла.

C>9.Непонятен смысл метода CompleteAdding().

Видимо вы не писали или не работали с блокирующими очередями Я вот тоже еще 10 дней назад о них не слышал, но сейчас я понимаю зачем нужен CompleteAdding(). И кстати оно слизанно со стандартной реализации блокирующей очереди в .Net 4.0

C>10.Для многопоточной записи/выборки объектов используется ConcurrentQueue. При ее использовании куча локов уходит.

да, у меня первый класс (тут его не показывал) тоже реализовывал задание 5 строчками — был просто пустой класс наследник от стандартной блокирующей очереди, но я решил что такое за тестовое задание не защитают Да и C# попробовать хотелось, поэтому написал свой велосипед — все-таки это тестовое задание...

    public class BegBlockedQueue1<T> : BlockingCollection<T>
    {
        public BegBlockedQueue1() : base(new ConcurrentQueue<T>())
        {
        }

        public BegBlockedQueue1(int boundedCapacity) : base(new ConcurrentQueue<T>(), boundedCapacity)
        {
        }
    }



C>В целом код неплохой довольно.

это радует
--
Блог шароварщика ::Микроблог про wxWidgets
Re[3]: Уши C++ или C++ style vs C# style
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.08.12 16:02
Оценка:
Здравствуйте, Begemot_, Вы писали:

C>>4.Внутри lock вроде дополнительный Monitor.Wait не нужен.

B_>ну это зависит от логики приложения В блокирующей очереди нужен иначе работать не будет.
Объясните плиз, зачем вы используете Pulse-ы и Wait-ы таким образом?

C>>В целом код неплохой довольно.

B_>это радует

Согласен что неплохой, и C++-ом не пахнет. Есть вопросы, но они не к коду, а к пониманию lock/Wait и т.п.
Да, а зачем при lock-ах используется ConcurrentQueue? Что за перестраховка?
Re: работодатель - ЛК ? (-)
От: blacksun  
Дата: 29.08.12 16:10
Оценка:
Re[4]: Уши C++ или C++ style vs C# style
От: fddima  
Дата: 29.08.12 18:33
Оценка: +1
Здравствуйте, samius, Вы писали:

S>Согласен что неплохой, и C++-ом не пахнет. Есть вопросы, но они не к коду, а к пониманию lock/Wait и т.п.

S>Да, а зачем при lock-ах используется ConcurrentQueue? Что за перестраховка?
ТС ConcurrentQueue и не использует.
Re[5]: Уши C++ или C++ style vs C# style
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.08.12 18:35
Оценка: :)
Здравствуйте, fddima, Вы писали:

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


F> ТС ConcurrentQueue и не использует.


Точно нет... А как она мне причудилась?!?! Вопрос, конечно снимается.
Re[4]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 18:57
Оценка: +1
Здравствуйте, samius, Вы писали:

B_>>ну это зависит от логики приложения В блокирующей очереди нужен иначе работать не будет.

S>Объясните плиз, зачем вы используете Pulse-ы и Wait-ы таким образом?

Это блокирующая очередь, она работает следующим образом
1. Первый поток производитель что-то делает, и добавляет задания в очередь используя Add()
2. Второй поток потребитель — берет задания из очереди и обрабатывает их.

При этом
1. если потребитель пытается что-то добавить задачу в очередь которая уже полная (количество задач == максимально разрешенному), то очередь блокирует его выполнение до тех пор, пока потребитель не освободит место в очереди
2. если потребитель, работает быстрее производителя, и пытается взять задачу из пустой очереди, очередь блокирует выполнение производителя до тех пор пока потребитель не добавит задачу.

Отсюда,


 public void Add(T item)
        {
            lock (_locker)
            {
                while (TryAdd(item) == false)
                    Monitor.Wait(_locker);
            }
        }


lock нужен для синхронизации доступа между потоками — обыкновенная реализация потокобезопасности. Дальше мы входим в процедуру TryAdd которая пытается добавить задание не используя блокировку потока, если она вернула False значит очередь переполнена, и мы в Add должны заблокировать поток производителя пока не придет потребитель и не заберет задачу из очереди, освободив нам место. Для этого вызывается Monitor.Wait(_locker); — он снимает lock с объекта давая другому потоку возможность забрать задание и ждет сигнала. Когда получен сигнал — мы опять вызываем TryAdd и так пока не получится добавить.

В свою очередь Take() (вызываемая из потока потребителя) после появления свободного места в очереди вызывает Monitor.Pulse(_locker);, Этот сигнал получает поток потребителя заблокированный Waitом и понимает что нужно еще раз проверить условия while (TryAdd(item) == false) — при успешном добавлении производитель разблокируется.

Точно так же работает Wait в Take() — если нет ничего в очереди, блокируем потребителя, и ждем Pulse от процедуры Add()\TryAdd...

Про работу Wait\Pulse доступно написано тут http://rsdn.ru/article/dotnet/CSThreading2.xml#EH6AE
Автор(ы): Joseph Albahari
Дата: 27.06.2007
Окончание статьи, опубликованной в RSDN Magazine #1-2007. Рассматриваются особенности взаимодействия с апартаментами, потоковые таймеры, пулы потоков, BackgroundWorker, асинхронные методы и делегаты.
В статье использован материал из книги Joseph Albahari, Ben Albahari "C# 3.0 in a Nutshell" — http://www.oreilly.com/catalog/9780596527570/
--
Блог шароварщика ::Микроблог про wxWidgets
Re[2]: работодатель - ЛК ? (-)
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 18:59
Оценка:
Здравствуйте, blacksun, Вы писали:

Да, скорее всего именно ЛК.
--
Блог шароварщика ::Микроблог про wxWidgets
Re[5]: Уши C++ или C++ style vs C# style
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.08.12 19:14
Оценка:
Здравствуйте, Begemot_, Вы писали:

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


B_>>>ну это зависит от логики приложения В блокирующей очереди нужен иначе работать не будет.

S>>Объясните плиз, зачем вы используете Pulse-ы и Wait-ы таким образом?

B_>Это блокирующая очередь, она работает следующим образом

B_>1. Первый поток производитель что-то делает, и добавляет задания в очередь используя Add()
B_>2. Второй поток потребитель — берет задания из очереди и обрабатывает их.

B_>При этом

B_>1. если потребитель пытается что-то добавить задачу в очередь которая уже полная (количество задач == максимально разрешенному), то очередь блокирует его выполнение до тех пор, пока потребитель не освободит место в очереди
B_>2. если потребитель, работает быстрее производителя, и пытается взять задачу из пустой очереди, очередь блокирует выполнение производителя до тех пор пока потребитель не добавит задачу.

Теперь ясно, я просто задачу не понял.

B_>Отсюда,

...
B_>Про работу Wait\Pulse доступно написано тут http://rsdn.ru/article/dotnet/CSThreading2.xml#EH6AE
Автор(ы): Joseph Albahari
Дата: 27.06.2007
Окончание статьи, опубликованной в RSDN Magazine #1-2007. Рассматриваются особенности взаимодействия с апартаментами, потоковые таймеры, пулы потоков, BackgroundWorker, асинхронные методы и делегаты.
В статье использован материал из книги Joseph Albahari, Ben Albahari "C# 3.0 in a Nutshell" — http://www.oreilly.com/catalog/9780596527570/


Я знаю эти методы, просто не воткнулся в задачу и код читал по диагонали. Даже ConcurrentQueue примерещилась

А IsAddingCompleted не нужно ли сделать volatile?
Re[6]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 19:22
Оценка:
Здравствуйте, samius, Вы писали:


S>А IsAddingCompleted не нужно ли сделать volatile?

не готов ответить, никогда серьёзно с потоками не работал, можно сказать первый опыт многопоточного программирования. Про volatile конечно читал пару раз, когда попадалась информация, но не четкого понимания что она делает, а сейчас я не в том состоянии что бы разбираться
--
Блог шароварщика ::Микроблог про wxWidgets
Re[7]: Уши C++ или C++ style vs C# style
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.08.12 19:29
Оценка:
Здравствуйте, Begemot_, Вы писали:

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



S>>А IsAddingCompleted не нужно ли сделать volatile?

B_>не готов ответить, никогда серьёзно с потоками не работал, можно сказать первый опыт многопоточного программирования. Про volatile конечно читал пару раз, когда попадалась информация, но не четкого понимания что она делает, а сейчас я не в том состоянии что бы разбираться
Ок, принято. Подозрительно что оно устанавливается внутри lock, опрашивается в том числе вне lock и имеет protected доступ на запись, причем _locker в наследниках не доступен.

Но конечно, не сейчас об этом.
Re[4]: Уши C++ или C++ style vs C# style
От: vmpire Россия  
Дата: 29.08.12 19:32
Оценка:
Здравствуйте, GGoga, Вы писали:

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


V>>Вот с этим утверждением я бы поспорил.

V>>Наша контора несколько лет назад отказалась от тестовых заданий, о чём я давно жалею.
V>>Тестовым заданием на раз отсекаются пионеры-теоретики, которые где-то что-то слышали, но как применять не знают. В конце концов, человек-то берётся код писать, а не про ООП рассказывать. Рассказывать-то мнегие мастера.

V>>Я бы тестовое задание давал. И сам я такие делал, когда искад работу.

V>>Конечно, тестовое задание не должно быть на какие-то специальные знания, только если эти знания составляют обязательные требования.
V>>Но вот когда человек, декларирующий хорошее знание SQL не может в уме вычислить результаты простого држойна — это настораживает.

GG>Ок, тогда могу ли я, в ответ на просьбу о написании тестового задания, попросить аванс, чтобы проверить платежеспособность работодателя? Да на такой вопрос работодатель "обезумеет от наглости" соискателя.

Аналогия весёлая, но, к сожалению, неверная. Почему — см. дальше.

GG>А то получается, что в процессе найма только одна тестируемая сторона — соискатель. А то, что работодатель может быть "г...ном" всегда умалчивается.

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

GG>Куча фирм ищут сотрудников без тестовых заданий и как-то себе выживают и даже деньги зарабатывают. Т.е. получается, что им удается отсеивать плохих кандидатов.

...И в куче фирм в результате работают толпы идиотов, которых приходится вытягивать более опытным сотрудникам.
Это вообще не аргумент. Как минимум потому, что не учтено сколько фирм заглохло из за профнепригодности персонала.

GG>Мне лично все равно, кто и как относится к тестовым заданиям. Я просто даже не пойду на собеседование в фирму, которая просит выполнить такое задание (да, фирмы мечты у меня нет, а на нынешнем рынке труда многие платят одинаковые деньги),

Это ваше право, которого у вас никто не отнимает. Если отсутствие тестового задания для вас критерий адекватности фирмы — можете смело отсеивать такие фирмы.

GG>потому что под "всего лишь 2 часами потраченного времени" прячется 2 реальных дня, потому что если напишешь за те же 2 часа получишь — "вот здесь можно было бы написать так, сделать еще то-то и то-то, да дописать такое-то", спросив, что этого не было в требованиях — "ну это само по себе подразумевалось..." — занавес...

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

GG>Почитайте данный форум и найдете кучу тем, где кандидат (ТС не исключение) написал тестовое задание, а его не взяли. Он выставил его здесь "напоказ", а оказывается, что и придраться то не к чему, кроме небольшого отступа и открывающейся фигурной скобки на на отдельной строчке.

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

GG>Все имхо, но мое отношение к тестам — резко отрицательное. Нервы и личное время дороже и можно вполне устроиться без оного.

Я бы давал тестовые задания только в том случае, если проверять их буду тоже я
Кстати, одна из причин отказа нашей фирмы от тестовых заданий как раз в том, что многие не хотят его делать.
Но есть и обратная сторона: без тестового задания сильно увеличивается поток левых людей.
Вот не далее как на этой неделе искал человека в команду. Типичное резюме: образование высшее но не профильное, 25 лет, опыт работы по спецальности 2 года программистом в не программерской конторе, позиционирует себя как ведущего программиста, хочет 80000 рублей (Питерские цены). А на тестовом задании он бы сразу отсеялся.
Кстати, есть мысль: давать тестовое задание, но с автоматической его проверкой. Как бы вы к этому отнеслись?
Re: Уши C++ или C++ style vs C# style
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 29.08.12 19:35
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>Из того что я вижу тут не try C#, это неиспользование var для локальных переменных, а явное указание типа. Решарпер настойчиво предлагал их использовать, но я не согласился. Что еще тут не так?


#define TestBegBlockedQueue1 и #if TestBegBlockedQueue1 скорее всего. Все-таки тесты
для роботов (continuous integration) создаются в первую очередь, а подобные конструкции
требуют человеческого вмешательства. Уж если есть две реализации, то и тест-классов
должно быть два.
El pueblo unido jamás será vencido.
Re[5]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 19:42
Оценка:
Здравствуйте, vmpire, Вы писали:

V> Но тут есть ещё один нюанс, почему так может происходить, если хотите, расскажу, как проверка тестового задания выглядит изнутри и почему хорошее тестовое задание может быть "не принято"

Мне интересно было бы послушать, я первый раз делаю тестовое задание, как-то раньше не приходилось. А в будущем еще буду думаю, так что интересно послушать как оно с другой стороны...
--
Блог шароварщика ::Микроблог про wxWidgets
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 19:47
Оценка:
Здравствуйте, bl-blx, Вы писали:


BB>#define TestBegBlockedQueue1 и #if TestBegBlockedQueue1 скорее всего. Все-таки тесты

BB>для роботов (continuous integration) создаются в первую очередь, а подобные конструкции
BB>требуют человеческого вмешательства. Уж если есть две реализации, то и тест-классов
BB>должно быть два.
ну тут немножко не так все. Все таки это тестовое задание и никакой continuous integration тут не будет. К тому же первая реализация, была просто пустым классом наследником стандартного класса — скорее шуткой, и тестировать ее точно не надо, разве что проверить работу тестов. Тестировать надо только вторую — так что частое человеческое вмешательство не предполагается. Можно было конечно разнести на два класса простым копи\пейстом, но было важно что бы вторая реализация проходила именно те тесты которые прошли на первой, поэтому сделал одну базу кода с переключением, что бы при правке тестов не пришлось править одинаковый код в двух местах.
--
Блог шароварщика ::Микроблог про wxWidgets
Re[3]: работодатель - ЛК ? (-)
От: blacksun  
Дата: 29.08.12 19:59
Оценка:
Здравствуйте, Begemot_, Вы писали:

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


B_>Да, скорее всего именно ЛК.


Думаю не стоит искать черную кошку в темной комнате. HR сказал одно, ему лишь бы людей побольше окучить, да заданий разослать, а тот кто задания проверял может совсем другого мнения по 10 лет С++ и джуниорскую позицию C#, вот и выдал формальную причину. Я такое же задание как-то выполнял для ЛК, только на C++, позвонили на следующий день и пригласили на телефонное интервью. Код был самый обычный, обертка над std::queue, делал вечером после работы и не парился вообще — подход был формальный. Когда до очного интервью дошел, понял там что не боги горшки обжигают, а обычные люди там работают.
Re[6]: Уши C++ или C++ style vs C# style
От: vmpire Россия  
Дата: 29.08.12 20:18
Оценка: 11 (4) +1
Здравствуйте, Begemot_, Вы писали:

V>> Но тут есть ещё один нюанс, почему так может происходить, если хотите, расскажу, как проверка тестового задания выглядит изнутри и почему хорошее тестовое задание может быть "не принято"

B_>Мне интересно было бы послушать, я первый раз делаю тестовое задание, как-то раньше не приходилось. А в будущем еще буду думаю, так что интересно послушать как оно с другой стороны...
Тут есть два варианта, хороший и плохой. Заранее, к сожалению, не узнать, так как даже в одной фирме могут этим заниматься разные люди.

Хороший вариант:
Тестовое задание проверяет ведущий программист проекта, в который нужен человек.
В этом случае, так как человек ему нужен лично, он во первых будет проверять задание сам, а во вторых не будет обращать внимание на всякую ерунду типа форматирования, скобок, формальных комментариев, префиксов...
Потому, что если на это в фирме даже есть стандарты то всегда можно их просто выдать человеку когда он придёт на работу, большинство очень быстро привыкает к новому стилю.
Но на что программист обязательно посмотрит — это внятность кода и отсутствие излишней запутанности (ведь код нужно потом сопровождать), на отсутствие ошибок, типичных для новичков (проверка, не наврал ли в резюме об опыте), иногда на имена переменных. Ну и на то, что код вообще компилируется и работает.
В общем, это скорее проверка на общую адекватность, чем окончательный вердикт. Для окончательного вердикта есть собеседование.
Обращаю внимание, что ведущий программист проекта не заинтересован в том, чтобы завернуть способного кандидата, он заинтересован ровно в обратном — ему же нужен человек и чем скорее он его найдёт тем скорее освободится от этой муторной в общем-то задачи.

Плохой вариант (встречается чаще среди крупных контор, но не всегда):
Набором персонала занимаются специальные люди из HR либо не технический менеджер проекта. Это чтобы максимально разгрузить технических специалистов, что при правильном подходе вполне возможно.
Сами они задание, естественно, проверить не могут, так как это в принципе не программмисты, поэтому отсылают тестовое задание двум-трём программистам, обычно тем, кто сейчас наименее загружен.
Вопрос к программистам при этом ставится примерно так: найти все недостатки кода.
Ну а программисты (особенно не загруженные) — народ увлекающийся и будут соревноваться кто больше чего найдёт. Поэтому находят обычно много, в основном, конечно, ерунды. Посмотрите, например, ответ Codechanger
Автор: Codechanger
Дата: 29.08.12
, который, говоря что код неплохой, тем не менее нашёл прилично недостатков.
Ну а дальше списки придирок объединяются и итог получается довольно большим. И смотрит на этот список менеджер и видит, что недостатков много, что все программисты что-то нашли (напоминаю, сам он серьёзность недостатков оценить не может) и думает: что-то мнего недостатков. Наверное, плохой код. Не будем брать.
Если кандидат спросит, что, собственно, не понравилось, в ответ ему высылают пару пунктов из этого списка, где, напоминаю, в основном несерьзные придирки. Кандидат остаётся в недоумении а фирма без работника.
Re: Уши C++ или C++ style vs C# style
От: G-Host  
Дата: 29.08.12 20:34
Оценка:
Здравствуйте, Begemot_, Вы писали:

это точно позиция на юниора?
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 29.08.12 20:45
Оценка:
Здравствуйте, G-Host, Вы писали:

GH>это точно позиция на юниора?

А хз, я так понял людей им надо не один и разных, ну по крайней мере пока они позиции закрыть не могут. А тестовое задание наверняка для всех одно. А мне без разницы, мне дали задание — я сделал
--
Блог шароварщика ::Микроблог про wxWidgets
Re: Уши C++ или C++ style vs C# style
От: ned Австралия  
Дата: 30.08.12 00:07
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>Лет 10 пишу в основном на С++ и немного на других языках, C# не пробовал. Предложили работу джуниором на С# честно сказал что его не знаю, но давно думаю освоить. Сказали — мы верим что с вашим опытом вы сможете, напишите тестовое задание, а мы посмотрим. Прочел полкнижки по шарпу, написал задание.


Нужно было прочитать всю книжку и подаваться на сеньора.
Серьезно. Я именно так и сделал. С аналогичным опытом. Сейчас консультирую "чистых" шарперов без C++ бэкграунда.
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 30.08.12 05:10
Оценка:
Здравствуйте, ned, Вы писали:


ned>Нужно было прочитать всю книжку и подаваться на сеньора.

ned>Серьезно. Я именно так и сделал. С аналогичным опытом. Сейчас консультирую "чистых" шарперов без C++ бэкграунда.
Да я так и хотел, вообще думал прочесть книжку, может сходить на курсы шарпа, у нас тут одна крупная контора организует, а только потом думать про работу. А тут компания сама написала мол идите к нам, я не очень хотел, но они убедили, а всю книжку не успел прочесть за неделю Через пару недель закончу, буду думать дальше
--
Блог шароварщика ::Микроблог про wxWidgets
Re: Уши C++ или C++ style vs C# style
От: SuhanovSergey  
Дата: 30.08.12 08:45
Оценка: 8 (1)
Здравствуйте, Begemot_, Вы писали:

B_>Задание вкратце "Необходимо реализовать блокирующую очередь и автоматические тесты к ней. Задача должна быть выполнена как можно более простым способом. .Net 3.5 or 4.0, + тесты, + отсутствие проблем с многопоточностью, + правильный стиль етс."


1. Возможно, решение показалось слишком многословным и не удовлетворяющим условию "как можно более простым способом". Это посчитали признаком C++ стиля. Классическое решение очень простое — требует всего лишь пары семафоров (http://en.wikipedia.org/wiki/Producer-consumer_problem).
2. Ваш BegBlockedQueue2 не реализует IEnumerable<T> и других итерфейсов, обычных для .net коллекций.
Re[5]: Уши C++ или C++ style vs C# style
От: GGoga  
Дата: 30.08.12 09:44
Оценка: +2
Здравствуйте, vmpire, Вы писали:

V>Аналогия весёлая, но, к сожалению, неверная. Почему — см. дальше.


Ок, фирма небольшая, работников так просто не выцепить. Где узнать о финансовых результатах? Ес-но начальство рассказывать будет о манне небесной и прочем, но в реальности может оказаться все иначе. Т.е. Ваше утверждение не всегда работает.

V>Ваша логическая ошибка в том, что вы предполагаете, что при найме отношения работник-работодатель симметричные, а это не так:

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

Спорный вопрос. Ваша же логическая ошибка в том, что Вы не видите, что на сегодня рынок как раз работника, а не работодателя. Сменить работу как минимум на аналогичные деньги, если они средние по рынку — не составляет труда и много времени. Т.е. проблем с трудоустройством (сейчас) нет. Плюс во многих случаях как раз работодатель не может прожить без сотрудника, потому что сроки проекта прошли "вчера" и если срочно не найти людей, то заказчик просто уйдет.

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

V>Это вообще не аргумент. Как минимум потому, что не учтено сколько фирм заглохло из за профнепригодности персонала.

А сколько не заглохло? А сколько раcширилось? Не вижу связи между тестовое задание — успех фирмы. ИМХО, многие фирмы загибаются не из-за плохих разработчиков, а из-за кривого менеджмента. Вы проверяете тестами руководителей? Уверен, что нет. А ведь успех в большей доли как раз от них и зависит. Т.е. тоже не аргумент.

V>Это вопрос адекватности оценивающих результаты. Хотя, тоже имеет право на существование. Например, если вы устраиваютесь на фирму, которая занимается передовыми разработками многопоточной обработки, то корректная реализация многопоточности может вполне подразумеваться.


Опять же, на вкус и цвет. Вы считаете, что только тестовое задание может помочь оценить кандидата, а я считаю, что и без этого можно обойтись.

V>Опять же вопрос адекватности проверяющих. Но тут есть ещё один нюанс, почему так может происходить, если хотите, расскажу, как проверка тестового задания выглядит изнутри и почему хорошее тестовое задание может быть "не принято"


V>Я бы давал тестовые задания только в том случае, если проверять их буду тоже я

V>Кстати, одна из причин отказа нашей фирмы от тестовых заданий как раз в том, что многие не хотят его делать.
V>Но есть и обратная сторона: без тестового задания сильно увеличивается поток левых людей.
V>Вот не далее как на этой неделе искал человека в команду. Типичное резюме: образование высшее но не профильное, 25 лет, опыт работы по спецальности 2 года программистом в не программерской конторе, позиционирует себя как ведущего программиста, хочет 80000 рублей (Питерские цены). А на тестовом задании он бы сразу отсеялся.
V>Кстати, есть мысль: давать тестовое задание, но с автоматической его проверкой. Как бы вы к этому отнеслись?

Что Вы понимаете под "автоматической проверкой"? Если бы у меня была "фирма мечты" и я бы любыми путями туда хотел попасть, то я бы делал и тестовое задание и вообще проходил бы все адекватные тестирования со стороны работодателя. Но! У меня такой фирмы нет, получить среднерыночную зп можно в большом числе компаний, которые не занимаются "тестированием", а отдают предпочтение классическим собеседованиям. А получить +200 у.е. можно и другими путями, причем с меньшими усилиями, чем пытаясь попасть в компанию, которая платит на эти 200 баксов выше рынка, но просит написать тестовое задание.

PS.: давайте закончим данную холиварную дискуссию, потому как лично я не хочу Вас переубеждать Ваше право давать и проверять тестовые задания, а "мое" — их не писать
Re[2]: Уши C++ или C++ style vs C# style
От: sysenter  
Дата: 30.08.12 10:59
Оценка: +4
Здравствуйте, Codechanger, Вы писали:

C>3.Привычка к ++i, а не i++.


И что в этом такого неправильного и архивредного, что на этом стоило акцентировать внимание?
Re[6]: Уши C++ или C++ style vs C# style
От: vmpire Россия  
Дата: 30.08.12 18:02
Оценка:
Здравствуйте, GGoga, Вы писали:

GG>Ок, фирма небольшая, работников так просто не выцепить. Где узнать о финансовых результатах? Ес-но начальство рассказывать будет о манне небесной и прочем, но в реальности может оказаться все иначе. Т.е. Ваше утверждение не всегда работает.

Для небольшой фирмы это, конечно, сложнее. Но можно, например, попросить провести мини-экскурсию по фирме, посмотреть, в каких условиях люди работают и мельком глянуть, что у них на экранах. Если видно, что на оборудовании экономят, то наверное здесь не всё хорошо. А если откажут в экскурсии — сразу посылать нафиг и искать других

V>>Но обычно работодатель без расширения штата может прожить гораздо дольше и комфортнее, чем человек без работы. Поэтому работодатель и может себе позволить такие вольности.

задание, достаточно прочитать отзывы о нём или спросить его текущих работников.
GG>Спорный вопрос. Ваша же логическая ошибка в том, что Вы не видите, что на сегодня рынок как раз работника, а не работодателя. Сменить работу как минимум на аналогичные деньги, если они средние по рынку — не составляет труда и много времени. Т.е. проблем с трудоустройством (сейчас) нет. Плюс во многих случаях как раз работодатель не может прожить без сотрудника, потому что сроки проекта прошли "вчера" и если срочно не найти людей, то заказчик просто уйдет.
Да, согласен, вопрос не однозначный. Да и фирмы бывают разные. Кто-то отлично проживёт без работника ещё несколько лет, а кто-то без расширения загнётся. Просто по моему личному опыту (без претензии на универсальность) первых больше.

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

V>>Это вообще не аргумент. Как минимум потому, что не учтено сколько фирм заглохло из за профнепригодности персонала.
GG>А сколько не заглохло? А сколько раcширилось?
GG>Не вижу связи между тестовое задание — успех фирмы.
А её напрямую и нет. Тестовое задание — способ немного упростить поиск программистов, но не замена личной встрече.

GG> ИМХО, многие фирмы загибаются не из-за плохих разработчиков, а из-за кривого менеджмента.

Менеджер — тоже работник фирмы. И от качества его работы успех фирмы, конечно, тоже зависит, так же, как и от программистов.

GG> Вы проверяете тестами руководителей? Уверен, что нет. А ведь успех в большей доли как раз от них и зависит. Т.е. тоже не аргумент.

Насчёт "в большей доли" не согласен, но это субъективно. А что до тестов — будь моя воля — проверял бы, но, к сожалению, это не в моей компетенции пока.

V>>Это вопрос адекватности оценивающих результаты. Хотя, тоже имеет право на существование. Например, если вы устраиваютесь на фирму, которая занимается передовыми разработками многопоточной обработки, то корректная реализация многопоточности может вполне подразумеваться.

GG>Опять же, на вкус и цвет. Вы считаете, что только тестовое задание может помочь оценить кандидата, а я считаю, что и без этого можно обойтись.
Я нигде не утверждал про "только". И обойтись без этого можно, но всё имеет свою цену — см. выше про толпы идиотов.

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

GG>Что Вы понимаете под "автоматической проверкой"?
Ну, типа как на олимпиадах по программированию. Программа имеет чёткий вход и выход, проверяется другой программой по входу-выходу.

GG>Если бы у меня была "фирма мечты" и я бы любыми путями туда хотел попасть, то я бы делал и тестовое задание и вообще проходил бы все адекватные тестирования со стороны работодателя. Но! У меня такой фирмы нет, получить среднерыночную зп можно в большом числе компаний, которые не занимаются "тестированием", а отдают предпочтение классическим собеседованиям. А получить +200 у.е. можно и другими путями, причем с меньшими усилиями, чем пытаясь попасть в компанию, которая платит на эти 200 баксов выше рынка, но просит написать тестовое задание.

Это уже с вашей стороны субъективизм. Спорить тут не о чем.

GG>PS.: давайте закончим данную холиварную дискуссию, потому как лично я не хочу Вас переубеждать Ваше право давать и проверять тестовые задания, а "мое" — их не писать

Я и не планировал никого ни в чём убеждать. Просто высказал своё мнение. Я же не даю вам тестовое задание
Re: Уши C++ или C++ style vs C# style
От: __kot2  
Дата: 30.08.12 23:14
Оценка: 2 (1)
Здравствуйте, Begemot_, Вы писали:
B_> BegBlockedQueue1<int> q = new BegBlockedQueue1<int>();
пишут обычно var q = new BegBlockedQueue1<int>();

B_> q.Add(2);

B_> q.Add(32);
B_> q.Add(212);
скорее всего это можно записать в стиле q = new BegBlockedQueue1<int>() {2, 32, 212};

B_> private bool _isAddingCompleted = false;

это лишнее. лучше авто-property public bool IsAddingCompleted { get; set; }

B_> // Maybe there is waiting producer inside Add

B_> if (IsAddingCompleted == false && Count == BoundedCapacity — 1)
== false
ну и в других местах это в глаза бросается

B_>namespace UnitTest

B_>{
B_>#if TestBegBlockedQueue1
B_> using TestClassImplementation = BegBlockedQueue1<int>;
B_>#else
B_> using TestClassImplementation = BegBlockedQueue2<int>;
B_>#endif
дефайны в C# не популярны

B_> for (int t = 0; t < 20; ++t)

и сильно любят foreach
Re[2]: Уши C++ или C++ style vs C# style
От: Философ Ад http://vk.com/id10256428
Дата: 30.08.12 23:43
Оценка:
Здравствуйте, SuhanovSergey, Вы писали:

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


B_>>Задача должна быть выполнена как можно более простым способом.

да, на это стоило обратить внимание, более того, заострить.

SS> ... слишком многословным и не удовлетворяющим условию...

похоже на то



SS>2. Ваш BegBlockedQueue2 не реализует IEnumerable<T> и других итерфейсов, обычных для .net коллекций.

круто, ч0!
здесь реализация этого интерфейса вообще-то сильно усложняет задание.
оно нужно?
Всё сказанное выше — личное мнение, если не указано обратное.
Re: Уши C++ или C++ style vs C# style
От: Философ Ад http://vk.com/id10256428
Дата: 31.08.12 00:14
Оценка:
Здравствуйте, Begemot_, Вы писали:

0)
 //Вот это нафига?
 //Зачем делать блокирующим метод Add()?
 public bool IsAddingCompleted
 public void CompleteAdding()

Вы когда-нибудь использовали очередь оконных сообщений windows?
Сама задача ну очень об этом напоминает.


1) Почему реализованы методы Add() / Take() а не Enqueue() / Dequeue ()?
Это всё-таки очередь!
У вас в стеке тоже будут Add/Take?

2) Метод Take() получился сложным: сложно проследить логику блокировок, из-за того, что TryTake() тоже использует блокировки. Надо проще.
-----------------------------
-----------------------------
В целом код читабельный и вполне понятный.
С таким кодом работать можно, спасибо.
Особенно порадовали пробельные строки между блоками кода внутри методов.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[3]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 31.08.12 06:06
Оценка: +1
Здравствуйте, Философ, Вы писали:


B_>>>Задача должна быть выполнена как можно более простым способом.

Ф>да, на это стоило обратить внимание, более того, заострить.
дык, я и обратил, в решении было две версии, первая вот


  public class BegBlockedQueue1<T> : BlockingCollection<T>
    {
        public BegBlockedQueue1() : base(new ConcurrentQueue<T>())
        {
        }

        public BegBlockedQueue1(int boundedCapacity) : base(new ConcurrentQueue<T>(), boundedCapacity)
        {
        }
    }


Куда уже более простой способ + полностью реализует что требуется. Хотя согласен, конструкторы тут просто перестраховка от смены используемого хранилища по умолчанию для BlockingCollection<T>, можно без них и это было бы проще



SS>> ... слишком многословным и не удовлетворяющим условию...

Ф>похоже на то
А что слишком многословно? Не считая конструкторов и свойств, в классе всего 5 функций из них 3 решают непосредственную задачу — адд, тейк, CompleteAdding. Две вспомогательные, но их код все равно нужен был поэтому я сделал отдельные функции доступные пользователю, можно было без них — но кода было столько же, то есть я бесплатно получил увеличение функционала + более красивый код. Никогда не думал что это плохо


Ф> //Зачем делать блокирующим метод Add()?

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


Ф> //Вот это нафига?

Ф> public bool IsAddingCompleted
Ф> public void CompleteAdding()
опять же — задача реализовать блокирующую очередь. Поставщик должен иметь возможность сообщить что все, работа сделана, больше заданий не будет. Иначе потребитель будет вечно ждать нового задания.


Ф>1) Почему реализованы методы Add() / Take() а не Enqueue() / Dequeue ()?

Ф>Это всё-таки очередь!
Ф>У вас в стеке тоже будут Add/Take?
Ну тут возможно ошибся и стоило писать Enqueue() / Dequeue (), но я слизовал интерфейс и функциональность со стандартной дотнетовской реализации — http://msdn.microsoft.com/en-us/library/dd267312(v=vs.100).aspx зачем выдумывать свое если лучшие собаководы уже все придумали Все методы которые у меня есть Add\Take\TryAdd\TryTake\CompleteAdding и свойства взяты оттуда.
К тому же указанные стандарт кодирования говорит:

"Старайтесь использовать имена с простым написанием. Их легче читать и набирать. Избегайте (в разумных пределах) использования слов с двойными буквами, сложным чередованием согласных. Прежде, чем остановиться в выборе имени, убедитесь, что оно легко пишется и однозначно воспринимается на слух. Если оно с трудом читается, и вы ошибаетесь при его наборе, возможно, стоит выбрать другое." (с) а у меня всегда была проблема с Enqueue/Dequeue, сложно читать\воспринимать на слух




Ф>2) Метод Take() получился сложным: сложно проследить логику блокировок, из-за того, что TryTake() тоже использует блокировки. Надо проще.

Эээ сложно проследить обычную логику потокобезопасности, не входить — пока переменная заблокирована? Ужас, неужели в шарпе все так плохо?
А почему замечания только к Take? Add использует точно такой же алгоритм и такую же "сложную" логику?
И было бы очень интересно посмотреть на более легкую реализацию этой задачи...

И вообще называть называть реализацию такого функционала 177 строчками, из которых больше сотни это пробелы и комментарии сложной... блин я все больше и больше хочу бросить С++ и писать на шарпе



Ф>В целом код читабельный и вполне понятный.

Ф>С таким кодом работать можно, спасибо.
Ф>Особенно порадовали пробельные строки между блоками кода внутри методов.
Ну дык, не для себя писал как обычно, а для людей
--
Блог шароварщика ::Микроблог про wxWidgets
Re[3]: Уши C++ или C++ style vs C# style
От: Codechanger Россия  
Дата: 31.08.12 07:11
Оценка:
Здравствуйте, sysenter, Вы писали:

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


C>>3.Привычка к ++i, а не i++.


S>И что в этом такого неправильного и архивредного, что на этом стоило акцентировать внимание?


Я не говорил, что это неправильно или архивредно
Re[2]: Уши C++ или C++ style vs C# style
От: Rudolf  
Дата: 03.09.12 13:28
Оценка: -1
Здравствуйте, Codechanger, Вы писали:

C>1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно


В С++ тоже не принято для булевых переменных, кстати. Это у ТС наследие pure C.

C>3.Привычка к ++i, а не i++.


Полезная, кстати, привычка. Лучше и в С++ и в С# всегда использовать префиксную форму, чтоб не париться насчет порядка выполнения при передаче в методы.
Вот например, C#:
        delegate int del(int n);

        static void f(del d)
        {
            int x = d(1);
            Console.WriteLine("Res = " + x.ToString());
        }

        static void Main(string[] args)
        {
            f( n => n++ );

            Console.ReadKey();
        }


На выходе будет 1, а не ожидаемое 2. А тот, кто привык к плюсАм, напишет ++n и получит на выходе 2.
Re: Уши C++ или C++ style vs C# style
От: Tom Россия http://www.RSDN.ru
Дата: 03.09.12 16:26
Оценка:
B_>        /// <summary>
B_>        /// Removes an item from the BegBlockedQueue2.
B_>        /// </summary>
B_>        /// <returns>The item removed from the collection..</returns>
B_>        public T Take()
B_>        {
B_>            lock (_locker) // <<<<<<<<<<<<<<<<<
B_>            {
B_>                T item;
B_>                while (TryTake(out item) == false)
B_>                {
B_>                    if (IsCompleted)
B_>                        throw new InvalidOperationException(); // Эээээээ????? Вызываем Take и на ровном месте получаем InvalidOperationException????????

B_>                    Monitor.Wait(_locker); // <<<<<<<<<<<<<<<<<<<<<??????????
B_>                }

B_>                return item;
B_>            }
B_>        }
B_>    }
B_>}


WTF???????

PS:
Это просто жЭсточайший код.
Народная мудрось
всем все никому ничего(с).
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 03.09.12 19:33
Оценка: :)
Здравствуйте, Tom, Вы писали:

Tom>WTF???????


Tom>PS:

Tom>Это просто жЭсточайший код.

Поразительно только, как это он работает, проходит тесты да и еще ведет себя очень похоже на аналогичную процедуру в фреймворке
--
Блог шароварщика ::Микроблог про wxWidgets
Re[2]: Уши C++ или C++ style vs C# style
От: Философ Ад http://vk.com/id10256428
Дата: 04.09.12 02:01
Оценка:
Здравствуйте, Tom, Вы писали:

// Эээээээ????? Вызываем Take и на ровном месте получаем InvalidOperationException????????

Tom>WTF???????



    class Program
    {
        static void Main(string[] args)
        {
            BegBlockedQueue2<int> queue = new BegBlockedQueue2<int>();
            queue.Add(1);
            //queue.CompleteAdding();
            while (!queue.IsCompleted)
            {
                Console.WriteLine(queue.Take());
            }
            Console.WriteLine("т.к. добавление не завершено, мы эту строку никогда не увидим");
            Console.ReadLine();
        }
    }


Что я делаю не так?
Всё сказанное выше — личное мнение, если не указано обратное.
Re[3]: Уши C++ или C++ style vs C# style
От: Аноним  
Дата: 04.09.12 04:11
Оценка:
Здравствуйте, Философ, Вы писали:


Ф>Что я делаю не так?

может быть не правильно используете блокирующую очередь?
Re[2]: Уши C++ или C++ style vs C# style
От: Sinix  
Дата: 04.09.12 05:22
Оценка: 14 (2)
Здравствуйте, Tom, Вы писали:

Tom>PS:

Tom>Это просто жЭсточайший код.

Это не код, это жизнь у blocking collection такая жестокая. Вот аналог из BCL:
// System.Collections.Concurrent.BlockingCollection<T>
public T Take()
{
    T result;
    if (!this.TryTake(out result, -1, CancellationToken.None))
    {
        throw new InvalidOperationException(SR.GetString("BlockingCollection_CantTakeWhenDone"));
    }
    return result;
}
Re: Уши C++ или C++ style vs C# style
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 04.09.12 14:13
Оценка:
Здравствуйте, Begemot_

Простейшая блокирующая очередь:
public sealed class Queue<T>
{
    private readonly System.Collections.Generic.Queue<T> queue = new System.Collections.Generic.Queue<T>();

    public void Enqueue (T x)
    {
        lock (this)
        {
            this.queue.Enqueue(x);
            System.Threading.Monitor.PulseAll(this);
        }
    }

    public T Dequeue ()
    {
        lock (this)
        {
            while (this.queue.Count == 0)
            {
                System.Threading.Monitor.Wait(this);
            }
            return this.queue.Dequeue();
        }
    }
}
Re[2]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 04.09.12 14:46
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Простейшая блокирующая очередь:


Да, простейшая, у меня более функциональная — поддерживает максимальный размер очереди и соответственно блокировку не только потребителя, но и поставщика.
--
Блог шароварщика ::Микроблог про wxWidgets
Re[3]: Уши C++ или C++ style vs C# style
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 05.09.12 12:26
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>Да, простейшая, у меня более функциональная — поддерживает максимальный размер очереди и соответственно блокировку не только потребителя, но и поставщика.


Простейшая блокирующая очередь с фиксированной ёмкостью блокирующая не только потребителя, но и поставщика:
public sealed class Queue<T>
{
    private readonly System.Collections.Generic.Queue<T> queue = new System.Collections.Generic.Queue<T>();
    private readonly int capacity;

    public Queue (int capacity)
    {
        if (capacity <= 0)
        {
            throw new System.ArgumentException("Invalid capacity");
        }
        this.capacity = capacity;
    }

    public void Enqueue (T x)
    {
        lock (this)
        {
            while (this.queue.Count == this.capacity)
            {
                System.Threading.Monitor.Wait(this);
            }
            this.queue.Enqueue(x);
            System.Threading.Monitor.PulseAll(this);
        }
    }

    public T Dequeue ()
    {
        lock (this)
        {
            while (this.queue.Count == 0)
            {
                System.Threading.Monitor.Wait(this);
            }
            System.Threading.Monitor.PulseAll(this);
            return this.queue.Dequeue();
        }
    }
}
Re[4]: Уши C++ или C++ style vs C# style
От: Begemot_ Россия http://softvoile.com/
Дата: 05.09.12 12:36
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:


СГ>Простейшая блокирующая очередь с фиксированной ёмкостью блокирующая не только потребителя, но и поставщика:

Ну и к чему это код? у меня точно такое же решение. Правда немного по другому выглядит, за счет дополнительной функциональности — но суть та же, что хотели сказать то?

К тому же у вас нет возможности сообщить что производитель закончил создавать задания надо закруглятся, потребитель запросит очередное задание и заблокируется навечено...
--
Блог шароварщика ::Микроблог про wxWidgets
Re[3]: Уши C++ или C++ style vs C# style
От: Rudolf  
Дата: 05.09.12 13:36
Оценка:
Здравствуйте, Rudolf, Вы писали:

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


C>>1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно


R>В С++ тоже не принято для булевых переменных, кстати. Это у ТС наследие pure C.


C>>3.Привычка к ++i, а не i++.


R>Полезная, кстати, привычка. Лучше и в С++ и в С# всегда использовать префиксную форму, чтоб не париться насчет порядка выполнения при передаче в методы.

R>Вот например, C#:
R>
R>        delegate int del(int n);

R>        static void f(del d)
R>        {
R>            int x = d(1);
R>            Console.WriteLine("Res = " + x.ToString());
R>        }

R>        static void Main(string[] args)
R>        {
R>            f( n => n++ );

R>            Console.ReadKey();
R>        }
R>


R>На выходе будет 1, а не ожидаемое 2. А тот, кто привык к плюсАм, напишет ++n и получит на выходе 2.


Вот drol несогласен с моим постингом. А с чем конкретно?
Re[4]: Уши C++ или C++ style vs C# style
От: Аноним  
Дата: 06.09.12 11:54
Оценка: -1
Monitor.Wait внутри лока и PulseAll внутри лока, вы уверены, что это будет работать?
Re[5]: Уши C++ или C++ style vs C# style
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 06.09.12 12:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Monitor.Wait внутри лока и PulseAll внутри лока, вы уверены, что это будет работать?


Абсолютно уверен. Это монитор Хоара.

Monitor.Wait и Monitor.PulseAll разрешается вызывать только внутри лока. В этом весь смысл.

Пока поток спит внутри Monitor.Wait он не лочит монитор, Monitor.Wait — это временный выход из лока.
Re[5]: Уши C++ или C++ style vs C# style
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.09.12 12:45
Оценка: +1 :)
Здравствуйте, Begemot_, Вы писали:

B_>К тому же у вас нет возможности сообщить что производитель закончил создавать задания надо закруглятся, потребитель запросит очередное задание и заблокируется навечено...


Это мелочовочка. У тебя код очень громоздкий, тяжко читать, а у Губанова в 5 сек.
Re[6]: Уши C++ или C++ style vs C# style
От: Sinix  
Дата: 26.09.12 13:08
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Это мелочовочка. У тебя код очень громоздкий, тяжко читать, а у Губанова в 5 сек.

Ну да, любая сложная задача имеет простое, легкое для понимания неправильное решение
Re[7]: Уши C++ или C++ style vs C# style
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.09.12 14:08
Оценка:
Здравствуйте, Sinix, Вы писали:

I>>Это мелочовочка. У тебя код очень громоздкий, тяжко читать, а у Губанова в 5 сек.

S>Ну да, любая сложная задача имеет простое, легкое для понимания неправильное решение

Где ошибка у Губанова ?
Re[8]: Уши C++ или C++ style vs C# style
От: Sinix  
Дата: 26.09.12 17:28
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Где ошибка у Губанова?

Неправильное решение необязательно означает ошибку С кодом всё в порядке, просто он, в отличие от кода топикстартера, не покрывает типовых сценариев для BlockingCollection. Конечно, можно похоливарить на тему "коллекция, блокирует — значит всё ок", но это будет чистейшей воды сфероконизм.

Достаточно добавить минимум необходимого — TryAdd/TryTake + возможность закрытия очереди, и получим примерно одинаковый по простоте и читаемости код.
Re[5]: Уши C++ или C++ style vs C# style
От: sergeyt4  
Дата: 26.09.12 20:01
Оценка:
Здравствуйте, Begemot_, Вы писали:

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


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

B_>Да я знаю что MS этого требования нету, но в том стандарте кодирования что мне дали написано что приватные поля класса должны начинаться с "_", и это кстати, единственное что мне там активно не понравилось Ну и решарпер с настройками по умолчанию тоже требует того же. Мне конечно не понравилось, но что делать сказали надо, значит надо. Тем более что отрефакторить готовый код перед отсылкой не сложно


>>К слову, топикстартера с таким кодом я бы взял, причём даже не на джуниора.

B_>Ну у меня тоже есть версия что отказали именно по этому, им вроде нужны джуниоры и когда я сказал что шарпа в глаза не видел — сказали, что ничего страшного, подойду. Видимо код их смутил, не стоило так серьёзно относится к тестовому заданию наверное

Да, скорей всего вы правы по поводу причины отказа — ваш код на джуниора не тянет, тут чувствуется гораздо более высокий уровень. Джуниор, как мне кажется, не додумался бы Monitor.Pulse/Wait использовать. Так что дело даже не в стиле оформления.

А по поводу префиксов не парьтесь — их практически все используют — надо же как-то отличать локальные переменные от полей. А писать this постоянно — утомительно и громоздко.
Re[2]: Уши C++ или C++ style vs C# style
От: alexzz  
Дата: 28.09.12 10:19
Оценка:
C>1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно

Не принято, но вообще имеет смысл. Я сознательно в своём коде в условиях пишу if (condition == false) вместо if (!condition) просто потому, что эту false всегда легко видно (студия ещё и цветом выделяет как ключевое слово), а восклицательный знак маленький, иногда его не замечаю. Впрочем, я на C# за деньги не пишу, так что могу творить в своём коде всё, что хочу.
Re[3]: Уши C++ или C++ style vs C# style
От: sergeyt4  
Дата: 28.09.12 11:31
Оценка:
Здравствуйте, alexzz, Вы писали:

C>>1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно


A>Не принято, но вообще имеет смысл. Я сознательно в своём коде в условиях пишу if (condition == false) вместо if (!condition) просто потому, что эту false всегда легко видно (студия ещё и цветом выделяет как ключевое слово), а восклицательный знак маленький, иногда его не замечаю. Впрочем, я на C# за деньги не пишу, так что могу творить в своём коде всё, что хочу.


Не принято, потому что в отличие от C++ в C# и так нельзя в if() подсунуть что-либо другое, кроме bool.

Писать if (b == false) имеет смысл только в случае, когда b имеет тип bool? (nullable bool). Тогда b может иметь три значения: null, true, false.
Re: Уши C++ или C++ style vs C# style
От: Аноним  
Дата: 01.06.13 15:39
Оценка:
Stop hack the program!!!
message
Re[4]: Уши C++ или C++ style vs C# style
От: alexzz  
Дата: 01.06.13 15:55
Оценка:
Здравствуйте, sergeyt4, Вы писали:

C>>>1.Проверки на bool. Везде пишете ==false, в C# для булевых переменных не принятно обычно


A>>Не принято, но вообще имеет смысл. Я сознательно в своём коде в условиях пишу if (condition == false) вместо if (!condition) просто потому, что эту false всегда легко видно (студия ещё и цветом выделяет как ключевое слово), а восклицательный знак маленький, иногда его не замечаю. Впрочем, я на C# за деньги не пишу, так что могу творить в своём коде всё, что хочу.


S>Не принято, потому что в отличие от C++ в C# и так нельзя в if() подсунуть что-либо другое, кроме bool.

S>Писать if (b == false) имеет смысл только в случае, когда b имеет тип bool? (nullable bool). Тогда b может иметь три значения: null, true, false.

Раз уж тебя всплыла, ещё один довод в пользу явной проверки на false:

if (a && b && c == false)
{
}

if (!(a && b && c))
{
}

У оператора == приоритет ниже, чем у !, поэтому нет необходимости в лишних скобках, которые уменьшают читаемость кода.
Re: Уши C++ или C++ style vs C# style
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 01.06.13 15:57
Оценка:
Маленький комент не совсем по теме: "реализовать" переводится как "to implement", а "to realize" означает "осознать".
Ce n'est que pour vous dire ce que je vous dis.
Re: Уши C++ или C++ style vs C# style
От: a_g_99 США http://www.hooli.xyz/
Дата: 01.06.13 16:19
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>Больше комментариев нет, а мне вот интересно что-же так такого страшного? Если бы дело в том что плохо написал задание, там какие-то проблемы или плохой код — я бы понял, но смущает именно упор на том что это "написано не на С#". Кто-нибудь может показать вкратце где тут проблемы и как надо было правильно делать.


Долго разрабатываю на С++ & C#. Если не придираться к мелочам — ваш код хороший, каких-либо концептуальных проблем. Главная ошибка которую вы допустили — написали слишком хороший и сложный код для понимания дебилам которые его проверяли. Если вы огорчены, то рассматривайте "эту неудачу" как науку на будущее. Есть старая пословица — у обычного software developer при виде технического представителя работодателя вид должен быть лихой и придурковатый. А вы их вместо этого унижаете вместо этого своим интеллектом. Теоретически надо радоваться, но я не нахожусь в вашей ситуации
Re[4]: Уши C++ или C++ style vs C# style
От: Аноним  
Дата: 01.06.13 17:49
Оценка:
Здравствуйте, GGoga, Вы писали:

GG>Все имхо, но мое отношение к тестам — резко отрицательное. Нервы и личное время дороже и можно вполне устроиться без оного.

Если я сижу без работы, то всегда пишу все тестовые задания, даже те которые на неделю и особенно по незнакомым темам — чисто в порядке собственного экспириенса.
Re[3]: Уши C++ или C++ style vs C# style
От: Аноним  
Дата: 01.06.13 18:11
Оценка:
Здравствуйте, Философ, Вы писали:

SS>>2. Ваш BegBlockedQueue2 не реализует IEnumerable<T> и других итерфейсов, обычных для .net коллекций.

Ф>круто, ч0!
Ф>здесь реализация этого интерфейса вообще-то сильно усложняет задание.
Ф>оно нужно?
Нужно... Автора просили писать в стиле С#, а IEnumerable<T> это и есть часть стиля C#.
Оттого и не понравились, наверное, циклы for, ибо IEnumerable работает с foreach.
Re: Уши C++ или C++ style vs C# style
От: -n1l-  
Дата: 12.08.13 03:52
Оценка: 1 (1) -1
Здравствуйте, Begemot_, Вы писали:

B_>Лет 10 пишу в основном на С++ и немного на других языках, C# не пробовал.

Возьмите меня в подаваны? Пожалуйста.

B_>Прочел полкнижки по шарпу, написал задание. Вердикт был в стиле "вы были правы, это написано на с++, а не c#, так что к сожалению не подойдете".

Они не правы.

B_> Предложили работу джуниором на С# честно сказал что его не знаю, но давно думаю освоить. Сказали — мы верим что с вашим опытом вы сможете, напишите тестовое задание, а мы посмотрим.

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

B_>Больше комментариев нет, а мне вот интересно что-же так такого страшного? Если бы дело в том что плохо написал задание, там какие-то проблемы или плохой код — я бы понял, но смущает именно упор на том что это "написано не на С#". Кто-нибудь может показать вкратце где тут проблемы и как надо было правильно делать.


Я нашел в вашем коде недостаток, который видимо заметили работодатели.
Барабанная дробь!
В вашем коде не применены интерфейсы.
Вы наверное удивлены, но это самый основной недостаток, который я увидел. Другое, как справедливо заметили предыдущие коллеги — мелочи.
Дело в том, что когда вас просят написать какой-то класс на c#, особенно когда это коллекция, нужно задуматься о применении интерфейсов. IEnumerable<T>, ICollection<T>, IQueue<T>.
Благодаря этим интерфейсам, вы зададите архитектуру класса которая вам нужна, без доп. коллекций(видимо этого от вас ждали).
Плюс, вам станут доступны методы из LINQ для этих коллекций.
For example, вы хотите реализовать связанный список на C#, реализуете в своем связанном списке интерфейс IEnumerqable<T> и вот по вашему списку можно пройти циклом Foreach.
По вашей коллекции нельзя, к сожалению.
Вот собственно и все. Может кто-то найдет еще что-то. Но я думаю у вас там с многопоточностью все в порядке.
Re: Уши C++ или C++ style vs C# style
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.08.13 06:50
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>p.s. Вопрос не о том сделано ли задание хорошо или плохо, вопрос о стиле кода — что в нем неправильного с точки зрения C# и что показывает на привычку писать на C++.


Предлагаю просто поставить resharper, прогнать проверки на StyleCop и Visual Studio Code Analysis\FxCop.

Разговоры о стиле кода на форуме бесполезны.
Re: Уши C++ или C++ style vs C# style
От: achmed Удмуртия https://www.linkedin.com/in/nail-achmedzhanov-9907188/
Дата: 14.08.13 17:39
Оценка:
Здравствуйте, Begemot_, Вы писали:

B_>Лет 10 пишу в основном на С++ и немного на других языках, C# не пробовал. Предложили работу джуниором на С# честно сказал что его не знаю, но давно думаю освоить. Сказали — мы верим что с вашим опытом вы сможете, напишите тестовое задание, а мы посмотрим. Прочел полкнижки по шарпу, написал задание. Вердикт был в стиле "вы были правы, это написано на с++, а не c#, так что к сожалению не подойдете".


Нормальный код. Может быть усомнились в других качествах, а в официальном ответе просто соврали.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.