Ответы пользователя Чак Норрис - CodeHelper

Чак Норрис

Чак Норрис
Карма 3384
Имя Неизвестно
Возраст Неизвестно
Сайт Неизвестно
Twitter Неизвестно
Участвует в проекте 1105 дн., 12 час., 35 мин.
Последняя активность 536 дн., 21 час., 26 мин. назад
О себе ничего не указано

Ответы

Новые Лучшие
1
...
7
8
9
10
11
12
Перейти к вопросу →

Можно реализовать простейший алгоритм Фишера-Ятеса (Fisher–Yates shuffle). Говорят даже, что этот алгоритм упоминается в книгах Кнута. Вот реализация через extension:

public static void Shuffle<T>(this IList<T> list)  
{  
    Random random = new Random();  
    int n = list.Count;  
    while (n > 1) {  
        n--;  
        int k = random.Next(n + 1);  
        T value = list[k];  
        list[k] = list[n];  
        list[n] = value;  
    }  
}
Перейти к вопросу →

Самой зрелой считается реализация от Yahoo:

Есть один минус — нужно использовать весь Javascript-стек от Yahoo.

Перейти к вопросу →

На самом деле вопрос сложнее чем кажется. Понятно, что если задается какая-то константная коллекция, то лучше определить ее массивом, а не списком. Однако, есть мнение, что массивы можно (и даже нужно) использовать более активно, в частности, возвращать из различных сервисов и репозиториев.

Например, рассмотрим два варианта одного и того же репозитория. Со списком:

// Вариант A
public interface ICustomerRepository {
    IList<Customer> GetAll();
}

С массивом:

// Вариант B
public interface ICustomerRepository {
    Customer[] GetAll();
}

Для варианта со списком имеем следующие преимущества:

  • возвращается объект, реализующий интерфейс (IList<>), а не экземпляр конкретного класса. Значит кокретный репозиторий может вернуть специфическую реализацию списка. Так, NHibernate может вернуть коллекцию с возможностью загрузки по требованию и тд.
  • Возвращается объект, удобный для клиента — списки легко сортировать, фильтровать и тд.

Но есть один недостаток, связанный с парадигмой императивного программирования — возвращаемый список является изменяемым (mutable), клиент легко может добавить/удалить элементы в списке. Но что произойдет если клиент скажем добавит элемент в список:

var allCustomers = CustomerRepository.GetAll();
allCustomers.Add(new Customer());

Добавится ли при этом объект new Customer() в репозиторий? Изменится ли при этом внутреннее состояние самого репозитория? Интерфейс (A) не дает ответы на эти вопросы.

Преимущества варианта с массивом:

  • Возвращается легковесный и наиболее простой объект;
  • Вариант работает даже в доисторических версиях .NET;
  • Возвращается относительно неизменяемый объект (immutable). Клиент все еще может изменить элементы массива, но его длинна остается постоянной. Это конечно не решение проблемы, но все же массив считается «более неизменяемым» чем список. То есть интерфейс (B) лучше отображает сущность метода GetAll — вернуть список объектов для чтения.
Перейти к вопросу →

Выбор случайных строк реализован в разных БД по разному и NHibernate не предоставляет никакой абстракции над этим механизмом. Но можно использовать расширяемость NHibernate и реализовать это самому. Сначала нужно создать собственную реализацию Order:

public class RandomOrder : Order
{
    public RandomOrder() : base("", true)
    {
    }

    public override string ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
    {
        // Здесь возвращаем команду генерации рандомного идентификатора 
        // (выбираем только одну строку)
        return "newid()";  // Для MS SQL Server
        return "RAND()";   // Для MySql
        return "RANDOM()";   // Для PostgreSQL
        return "RAND()";   // Для IBM DB2
    }
}

Затем этот класс можно использовать при работе с сессией:

public IList<Item> GetRandomItems(int count)
{
    return HibernateTemplate.Execute(
        session =>
        {
            var criteria = session.CreateCriteria(typeof(Item));
            criteria.AddOrder(new RandomOrder());
            return criteria.SetMaxResults(count).List<Item>();
        }
    );
}
Перейти к вопросу →

Похоже что в спецификациях SQL ничего нет про выборку случайных строк из таблицы. Тем не менее большинство движков баз данных поддерживает такую возможность, правда каждый по своему. Идея такая — используется сортировка не по полю, а по некоторому случайному числу, сгенерированному для каждой строки таблицы. Если взять первые n строк такой выборки, то они и будут содержать n случайных строк таблицы. Вот примеры SQL запросов:

MySql:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

PostgreSQL:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Microsoft SQL Server:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

IBM DB2:

SELECT column, RAND() as IDX 
FROM table 
ORDER BY IDX FETCH FIRST 1 ROWS ONLY

Oracle:

SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum = 1

Примеры взяты из статьи SQL to Select a random row from a database table. Во всех примерах выбирается одна случайная запись, но запросы легко обобщить на случай n записей.

Перейти к вопросу →

Да, можно. Нужно использовать те же методы, что и для обычных заглушек, только с окончанием MultiMock:

MockRepository.CreateMultiMock(...);
MockRepository.DynamicMultiMock(...);
MockRepository.PartialMultiMock(...);
MockRepository.StrictMultiMock(...);

И это является одной из фишек Rhino Mocks, потому что многие другие фреймворки такой возможности не предоставляют. Однако, в сообществе ведутся споры о целесообразности мокирования нескольких интерфейсов. В частности, говорится о том, что интерпретация одного и того же объекта в разных формах вредит читабельности теста, усложняет его и тд. Ведь если тест интерпретирует один объект как две разные сущности, значит он выполняет (как минимум) две операции над этим объектом, а отсюда следует что тест может быть разбит на 2 теста.

Перейти к вопросу →

Вообще считается, что есть 3 способа сжатия WCF трафика. Вот перевод источника:

  • На транспортном уровне, используя message encoder, который сжимает все данные проходящие через канал. Есть пример такого подхода в WCF SDK, [SDK Folder]TechnologySamples/Extensibility/MessageEncoder/Compression
  • На уровне сообщений, добавляя определенные метаданные к SOAP-сообщению и сжимая тело этого сообщения. Можно использовать специфический WCF binding или MessageInspector Behavior чтобы модифицировать тело сообщения. Вот пример такого подхода: WS-Compression for WCF.
  • Только для транспорта на протоколе Http (не наш случай) можно использовать поддержку сжатия самого протокола.

Ну и конечно не следует забывать про оптимизацию на уровне приложения а не на уровне WCF. Сами классы DataSet и DataTable довольно-таки тяжеловесные, хотя не могу сказать относится ли это к сериализации для передачи через WCF. Где-то попадалось, что для оптимизации сериализации датасетов нужно задать пару свойств:

ds.SchemaSerializationMode = SchemaSerializationMode.ExcludeSchema;
ds.RemotingFormat = SerializationFormat.Binary;
Перейти к вопросу →

Вот несколько extension`ов из Mono.Rocks:

Повторение действия несколько раз:

6.Times (i => Console.WriteLine (i));

Удобная реализация циклов for с инкрементом и декрементом:

6.UpTo (12, i => Console.WriteLine (i));
12.DownTo (6, i => Console.WriteLine (i));

А вот цикл Step спервого взгляда выглядит абсолютно нечитабельным:

5.Step (9, 2, i => Console.WriteLine (i));

Без сигнатуры и не разберешься

public static void Step (this int self, int limit, int step, Action<int> action)

Выполнение действия над каждой из строк многострочного текста:

@"
one
two
three".EachLine (line => Console.WriteLine (line));

Преобразование строки в значение enum определенного типа:

"Bar".ToEnum<Foo>()

Создание строки пути к элементу файловой системы из нескольких составляющих — намного удобнее чем вкладывать Path.Combine в себя несколько раз:

var path = new [] {"/home", "jb", "sources"}.PathCombine ();

Получение атрибутов для типа. Фактически можно использовать не только для типа, но и для свойства/метода/поля и тд:

var attribute = typeof (Bar).GetCustomAttribute<FooAttribute> ();
var attributes = typeof (Bar).GetCustomAttributes<FooAttribute> ();
Перейти к вопросу →

Если определить extensions для примитивных типов double, int и тд то можно интересно работать с единицами измерения и конвертацией:

var результатВМетрах = 5.Метров() + 7.Километров() + 18.Сантиметров();

PS Я не любитель называть методы русскими словами, просто так показалось нагляднее)

Перейти к вопросу →

Есть и такое радикальное мнение, что property injection можно использовать всегда. Большая куча свойств лучше большой кучи параметров конструктора. И с эстетической и с практической точки зрения. Единственное неудобство — при создании из IOC контейнера нет гарантии что клиент получает объект, у которого все свойства заполнены. Но на этот случай можно написать метод, проверяющий корректность всех свойств и выкидывающий exception в случае если что-то не проинжектилось. Большинство IOC-контейнеров поддерживают вызов init-методов после создания объекта. В итоге мы получаем: с одной стороны, в ioc контейнере осуществляется «строгая» проверка того что все свойства заполнены; с другой стороны, в любом другом месте (в юнит тестах, напрмер) мы можем легко обойти эту проверку и задавать только те свойства, которые нам нужны.


1
...
7
8
9
10
11
12
v1.7.123.556
© 2009—2010 CodeHelper FAQ | О сайте | Обратная связь | История изменений | Статьи
Creative Commons LicenseМатериалы сайта распространяются под лицензией Creative Commons Attribution-Share Alike 3.0 Unported.