Паттерны от Замутилова, или как нельзя писать код.
От: Bigger Российская Империя  
Дата: 01.08.07 09:04
Оценка: 13 (7) +1 -2 :))) :))) :))) :))) :))) :))
Просто наметки для небольшой статьи. Думал в о жизни, но там вряд ли к месту.
Спасибо за внимание

Коллеги, хочу поделиться с вами печальным опытом, а может он вам поможет.
В процессе написания данного опуса я получил кучу положительных эмоций, а так же переосмыслил практику принятия сотрудников на работу.
И так
Паттерн№1. В БД структура не важна
Данные в базе должны храниться не по типам, а как левая пятка скажет. Например:
Данные типа GUID могут храниться в поле типа nvarchar(500).
Для удобства работы с этим полем следует использовать
Паттерн №2. Необходимо проверять все, всегда и по полной программе.
Приведу пример использования этой "сладкой парочки". В БД, в текстовом поле храниться GUID для получения данных выполняется запрос и результат записывается в DataSet ds, и обрабатываем ds следующим образом:

DataTable tab = ds.Tables[0];
foreach(DataRow row in tab.Rows)
{
   if (ds.Tables[0].Rows[0]["idrole"] != null && 
       Convert.ToString(ds.Tables[0].Rows[0]["idrole"]).Length != 0 && 
       new Guid(Convert.ToString(ds.Tables[0].Rows[0]["idrole"])) != Guid.Empty)
   {
        _role = new UserRole(new   
                                             Guid(Convert.ToString(ds.Tables[0].Rows[0]["idrole"])));
   }
   .....
}


Согласитесь, данный подход вызывает уважение умению поставить тормоза на ровном месте.
Паттерн №3. К черту for
Данный подход позволяет насладиться радостью бытия на циклах с заранее известным количеством повторов. Итак, у нас есть контейнер с заранее известным количеством элементов, затаилии дыхание — код:

int n = -1;
// Заранее созданный и заполненный список
List<object> listObject;
while(++n < listObject.Count)
{
....
}

Самое замечательное то, что n может быть объявлено за пару экранов до места использования, или, если везет, как приватный член класса.
Паттерн №4. Пусть весь мир подождет.
Суть данного паттерна состоит в том, что запущен поток с какой-то задачей, основной поток должен дождаться его завершения, т.е. либо получен результат, либо превышено время ожидания. Имеем следующий код:


DateTime tm = DateTime.Now + new TimeSpan(timeout);
Thread.Start();
while (result != null && DateTime.Now < tm);


Все финиш, если ответ не придет до начала while, то мы вылетаем по таймауту. Финиш.

Паттерн №5. Бездумный копипаст.

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

Паттерн №6. Мой хук.

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

Паттерн №7. GoTo — да вы не ошиблись — именно GoTo. Причем желательно с парой меток, которые не используются, либо не сразу найдешь.

Паттерн №8. Объявление полей класса в самых неожиданных местах, хотя дурацкая студия сводит все потуги к нулю.

Паттерн №9. Если что-либо можно обернуть, то это следует обернуть 2 или 3 раза.
Встречаются чудные места в коде, дважды оборачивается DataGrid, а затем оборачиваются DataRow и DataColumn. Так наверное надежней.

Паттерн №10. На каждый чих компонент.
Выражается в следующем:
• В проекте 4 или 5 компонент наследников от Label, разлие между которыми в виде границ, заливке или наклоне букв.
• Огромное количество наследников DataGrid — отличие в количестве столбцов, фоне и заголовках.
• Ну и так далее, надеюсь паттерн понятен.
Паттерн №11. Впихни невпихуемое.
В бедный гуиный контрол запихивается не только логика презентативного слоя, но и львиная доля бизнес логики.
Например, наш любимый наследник DataGrid кроме полезных визуальных эффектов может сам добывать данные из базы, без посредников, посредством прибитого к нему гвоздями селекта.

Паттерн №12. Один раз в год сады цветут.
Данный паттерн плавно вытекает из 10 и 11, раз сделанный контрол может примениться один и только один раз.

Паттерн №13. Графический интерфейс он главный самый.

Если, что-то не срослось с ГУИ, то переписать можно все и бизнес слой и структуру данных в БД.

Паттерн №14. Синглтон быстрый.

Суть в следующем:


    class MyCoolSingleton
    {
        private static MyCoolSingleton _instance = new MyCoolSingleton();
        private MyCoolSingleton()
        {
            // Идет код инициализации
        }
        // Получаем ссылку на объект
        public static MyCoolSingleton Instance
        {
            get { return _instance; }
        }
        // Производим реиниализацию объекта
        public static MyCoolSingleton ReInit()
        {
            _instance = new MyCoolSingleton();
            return _instance;
        }
        // тело класса, нам оно не интересно
    }

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

Паттерн №15. Самоудовлетворение.
Данный паттерн позволяет значительно увеличить быстродействие следующих версий, за счет удаления подергивания различных коллекций.

int n = _controlPanel.Controls.Count;
if (cashObject.panel.Size != _controlPanel.Size)
{
   cashObject.panel.Size = _controlPanel.Size;
   cashObject.panel = _getControl(cashObject.panel, cashObject.that);
}
_controlPanel.Controls.Add(cashObject.panel);
cashObject.panel.BringToFront();
if (n < _controlPanel.Controls.Count)
while (n-- > 0)
    _controlPanel.Controls.RemoveAt(_controlPanel.Controls.Count - 1);


Паттерн №16. Сам с усам.
Данный паттерн, в переводе на нормальный язык означает то, что если коллеги и писали код в проекте, то писали криво и не правильно, поэтому при реализации функционала не следует оглядываться на их кривой код. Иллюстрацию можно увидеть в коде к паттерну № 2. Конструктор объекта UserRole принимает в качестве параметра Guid и производит проверки на соответствие аргумента гордому званию Guid'а, но на коллег надеяться нельзя, поэтому было произведено дублирование проверок до вызова конструктора. Аналогично, если нужно разработать новый функционал класса, то на интерфейс класса внимание не обращается, он тупо расширяется, при добавление новых возможностей в библиотеку, не проверяется наличие классов и их соответствие поставленным целям, классы тупо добавляются.

Паттерн №17. К черту комментарии.
Я пишу самодокументированный код, комментарии в паттерне № 14 добавил не автор рассматриваемых паттернов. Если вы не понимаете что скрывается в регионе «Рефлексия формы», то это говорит о вашей низкой квалификации.

Паттерн №18. Мне не нравиться.
Мне не нравиться реализация, таким образом, означает только то, что автор паттернов не знает, как это реализовать.

Паттерн №19. Я уже написал более тысячи строк.
Означает то, что автор паттернов не видит иного пути решения проблемы, зачастую созданным самим в результате реализации своих же паттернов.



P.S. При описании данных паттернов их автор не пострадал.
P.P.S. Код, написанный с использованием данных паттернов, в производство не пошел.


Программист — это шаман..., подарите бубен!
Re: Паттерны от Замутилова, или как нельзя писать код.
От: _ks_  
Дата: 01.08.07 11:51
Оценка: 2 (1)
Как я тебя понимаю!
У меня есть довольнение к твоему списку.
Итак:

№20. Наглядная уверенность.
Если надо указать контролу, что он должен или не должен прятаться, то код должен быть предельно ясен. Например:
if (UserAllowedToSeeManagerControls)
{
    controlX1.Visible = true;
    controlY2.Visible = true;
    //...
    controlZ26.Visible = true;
}
else
{
    controlX1.Visible = false;
    controlY2.Visible = false;
    //...
    controlZ26.Visible = false;
}


№21. Переменные — даст ис фантастиш!
Даже если переменная не нужна, её обязатнльо надо завести. Ибо самодокументация. Например:
bool ApplyNewLayout()
{
    string fileName = LayoutFileName;
    bool layoutLoaded = LoadLayout(fileName);
    return layoutLoaded;
}
Re[2]: Паттерны от Замутилова, или как нельзя писать код.
От: Vector Россия  
Дата: 01.08.07 12:40
Оценка: :))
Здравствуйте, _ks_, Вы писали:

Тоже дополню из недавнего... Как узнать размер вектора? Да очень просто!

UINT nIndex = 0;
for(; nIndex < someVec.size(); nIndex++)
{
}
if (nIndex == 1)
{
// Код
}
else if (nIndex)
{
// Код
}
else
{
// Код
}
Re: Паттерны от Замутилова, или как нельзя писать код.
От: Hobot Bobot США  
Дата: 01.08.07 13:29
Оценка:
Здравствуйте, Bigger, Вы писали:

B>Паттерн №14. Синглтон быстрый.


B>Суть в следующем:



B>
B>    class MyCoolSingleton
B>    {
B>        private static MyCoolSingleton _instance = new MyCoolSingleton();
B>        private MyCoolSingleton()
B>        {
B>            // Идет код инициализации
B>        }
B>        // Получаем ссылку на объект
B>        public static MyCoolSingleton Instance
B>        {
B>            get { return _instance; }
B>        }
B>        // Производим реиниализацию объекта
B>        public static MyCoolSingleton ReInit()
B>        {
B>            _instance = new MyCoolSingleton();
B>            return _instance;
B>        }
B>        // тело класса, нам оно не интересно
B>    }
B>

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

Что-то я никак не могу понять при чем тут потоки. Вот ReInit — это действительно ужас, но, опять же, независимо от количества потоков.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Re[2]: Паттерны от Замутилова, или как нельзя писать код.
От: Bigger Российская Империя  
Дата: 02.08.07 05:21
Оценка:
Здравствуйте, Hobot Bobot, Вы писали:

skip

HB>Что-то я никак не могу понять при чем тут потоки. Вот ReInit — это действительно ужас, но, опять же, независимо от количества потоков.


Если конструктор не пустой, и там происходит инициализация чего-либо достаточно долгое время, а происходит обращение к сему объекту в эту время, то получите веселое время.

Программист — это шаман..., подарите бубен!
Re[3]: Паттерны от Замутилова, или как нельзя писать код.
От: Hobot Bobot США  
Дата: 02.08.07 07:01
Оценка:
Здравствуйте, Bigger, Вы писали:

HB>>Что-то я никак не могу понять при чем тут потоки. Вот ReInit — это действительно ужас, но, опять же, независимо от количества потоков.


B>Если конструктор не пустой, и там происходит инициализация чего-либо достаточно долгое время, а происходит обращение к сему объекту в эту время, то получите веселое время.


Любое обращение к членам класса будет ожидать, пока не закончится выполнение статического конструктора класса (который, в данном случае, создает экземпляр синглтона). А выполнение статического конструктора ровно один раз, вне зависимости от количества потоков, которые обращаются к классу, гарантируется рантаймом. Так что ничего веселого, боюсь, не будет. Веселье начнется только после использования ReInit.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Re[4]: Паттерны от Замутилова, или как нельзя писать код.
От: Bigger Российская Империя  
Дата: 02.08.07 09:35
Оценка:
Здравствуйте, Hobot Bobot, Вы писали:


При многопоточности отлавил исключение об использовании неинициализированного объекта

Программист — это шаман..., подарите бубен!
Re: Паттерны от Замутилова, или как нельзя писать код.
От: Bigger Российская Империя  
Дата: 02.08.07 09:38
Оценка:
Уважаемый _FRED_, а с чем Вы не согласны.
Важно знать Ваше мнение, что-бы статья получилась более полной

Программист — это шаман..., подарите бубен!
Re: Паттерны от Замутилова, или как нельзя писать код.
От: Шебеко Евгений  
Дата: 02.08.07 10:04
Оценка:
В дополнение. Оригинал к сожалению давно удалён, поэтому восстанавливаю по памяти, в деталях могу соврать.

№ 22. Мы свой макроязык напишем

BEGIN_FUNCTION_BODY1(open_table,AnsiString,file_name)
...
  BEGIN_FOR(x,0,table.record_count)
  ...
  END_BLOCK
..
END_FUNCTION_BODY

BEGIN_FUNCTION_BODY1(close_table) (AnsiString file_name)
...
END_FUNCTION_BODY





#define BEGIN_FUNCTION_BODY( __FUNC_NAME,_TYPE1,_PARAMETER1 ) int __FUNC_NAME(_TYPE1 _PARAMETER1)\
{\
  dbg_print(Ansistring("Enter function ")+__FUNC_NAME);\
  int result=0;

#define END_FUNCTION_BODY\
  dbg_print(Ansistring("Finish function ")+__FUNC_NAME);\
  return result;\
}

#define BEGIN_FOR(_VARIABLE,_FROM,_TO) for(int _VARIABLE=_FROM;_VARIABLE<_TO;_VARIABLE++){

#define BEGIN_BLOCK {
#define END_BLOCK }
Re: Паттерны от Замутилова, или как нельзя писать код.
От: Шебеко Евгений  
Дата: 02.08.07 10:19
Оценка:
Немножко не в тему.
Вот это моя реализация интуитивно понятного интерфейса.
Ему уже много лет, но мне до сих пор стыдно
Потому что до сих пор меня все спрашивают: "Как нам удалить карты?"

Re[5]: Паттерны от Замутилова, или как нельзя писать код.
От: Димчанский Литва http://dimchansky.github.io/
Дата: 02.08.07 11:22
Оценка:
Здравствуйте, Bigger, Вы писали:

B>При многопоточности отлавил исключение об использовании неинициализированного объекта


Я не очень понял, о чём речь.
Паттерн нормального синглтона выглядит примерно так:

sealed class MySingleton
{
  private static readonly MySingleton instance = new MySingleton(); 

  private LoadBalancer() 
  {
    // Initialization
  } 

  public static MySingleton Instance
  {
    get { return instance; }
  }
}

.NET гарантирует потокобезопасную инициализацию статического члена instance.
Т.е. Вы хотите сказать, что вызов Instance произошёл раньше, чем проинициализировался instance?
Re[6]: Паттерны от Замутилова, или как нельзя писать код.
От: Димчанский Литва http://dimchansky.github.io/
Дата: 02.08.07 11:24
Оценка:
Конструктор от копи-паста остался Поправка:
sealed class MySingleton
{
  private static readonly MySingleton instance = new MySingleton(); 

  private MySingleton() 
  {
    // Initialization
  } 

  public static MySingleton Instance
  {
    get { return instance; }
  }
}
Re[6]: Паттерны от Замутилова, или как нельзя писать код.
От: Bigger Российская Империя  
Дата: 02.08.07 13:32
Оценка:
Здравствуйте, Димчанский, Вы писали:

skip

Д>.NET гарантирует потокобезопасную инициализацию статического члена instance.

Д>Т.е. Вы хотите сказать, что вызов Instance произошёл раньше, чем проинициализировался instance?

Вызов происходил во время инициализации

Программист — это шаман..., подарите бубен!
Re[7]: Паттерны от Замутилова, или как нельзя писать код.
От: Димчанский Литва http://dimchansky.github.io/
Дата: 02.08.07 13:38
Оценка:
Здравствуйте, Bigger, Вы писали:

B>Вызов происходил во время инициализации


О как!
Re[7]: Паттерны от Замутилова, или как нельзя писать код.
От: Hobot Bobot США  
Дата: 02.08.07 13:49
Оценка:
Здравствуйте, Bigger, Вы писали:

B>Вызов происходил во время инициализации


Только что набросал примерчик с вызовами во время инициализации... Вроде все ОК, все потоки дожидаются, пока тип будет проинициализирован полностью.
С другой стороны, я тут порылся в статьях — пишут, что такая рантайм может позволить доступ к недоинициализированному классу для того, чтобы избежать deadlock'ов. Например, если два класса используют друг друга в статических конструкторах.



class Class1
{
  public static readonly String Field;
  public static readonly String OppositeField;

  static Class1()
  {
    // дергаем Class2 для вызова его статического конструктора
    OppositeField = Class2.Field;

    // инициализируем поле
    Field = "Class1 Field";
  }
}


class Class2
{
  public static readonly String Field;
  public static readonly String OppositeField;

  static Class2()
  {
    // дергаем Class1 для вызова его статического конструктора
    OppositeField = Class1.Field;

    // инициализируем поле
    Field = "Class2 Field";
  }
}



Вот в этом случае одно из полей OppositeField получит значение null.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Re[2]: Паттерны от Замутилова, или как нельзя писать код.
От: Ромашка Украина  
Дата: 02.08.07 13:59
Оценка:
Шебеко Евгений пишет:
> Ему уже много лет, но мне до сих пор стыдно

Кстати, а как удалить карты???
Posted via RSDN NNTP Server 2.1 beta


Всё, что нас не убивает, ещё горько об этом пожалеет.
Re[2]: Паттерны от Замутилова, или как нельзя писать код.
От: cvetkov  
Дата: 02.08.07 14:43
Оценка: :))
Здравствуйте, _ks_, Вы писали:

__>№21. Переменные — даст ис фантастиш!

__>Даже если переменная не нужна, её обязатнльо надо завести. Ибо самодокументация. Например:
__>
__>bool ApplyNewLayout()
__>{
__>    string fileName = LayoutFileName;
__>    bool layoutLoaded = LoadLayout(fileName);
__>    return layoutLoaded;
__>}
__>

А что в этом плохого? или предпочитаете так?
                    System.Diagnostics.Debug.Assert(
                        AlgUtil.Invoke<bool>(
                        delegate {
                            return !AlgUtil.Contains(
                                AlgUtil.Zip(
                                    AlgUtil.ToTyped<SciObject>(
                                        ((SciClassPart)AlgUtil.Find(
                                            AlgUtil.Iterate(
                                                (SciObject)t.t1,
                                                delegate(SciObject o) { return o.ContainingScope; }
                                            ),
                                            delegate(SciObject o) { return o is SciClassPart; }
                                        )).DeclaredElements
                                    ),
                                    AlgUtil.ToTyped<SciObject>(
                                        ((SciClassPart)AlgUtil.Find(
                                            AlgUtil.Iterate(
                                                (SciObject)t.t2,
                                                delegate(SciObject o) { return o.ContainingScope; }
                                            ),
                                            delegate(SciObject o) { return o is SciClassPart; }
                                        )).DeclaredElements
                                    )
                                ),
                                delegate(T<SciObject, SciObject> pair) {
                                    if(pair.t1 is SciMember) {
                                        if(!(pair.t2 is SciMember)) {
                                            return true;
                                        } else if(!((SciMember)pair.t1).Signature.Equals(((SciMember)pair.t2).Signature, StringComparison.InvariantCultureIgnoreCase)) {
                                            return true;
                                        }
                                    }
                                    return false;
                                });
                        }));

И ни одной переменной!
Re[3]: Паттерны от Замутилова, или как нельзя писать код.
От: _ks_  
Дата: 02.08.07 14:50
Оценка:
Сравнили х.. с пальцем.
Re[3]: Паттерны от Замутилова, или как нельзя писать код.
От: elmal  
Дата: 02.08.07 14:55
Оценка:
Здравствуйте, Ромашка, Вы писали:

Р>Кстати, а как удалить карты???

А я кажется дагадался, причем быстро, меньше чем за минуту . Нужно выделить карты, выбрать "отметить для удаления", а затем нажать сохранить. Правильно ?
Re: Паттерны от Замутилова, или как нельзя писать код.
От: Vova123  
Дата: 02.08.07 15:39
Оценка: +2
Здравствуйте, Bigger, Вы писали:

B>

B>Паттерн №13. Графический интерфейс он главный самый.

B>Если, что-то не срослось с ГУИ, то переписать можно все и бизнес слой и структуру данных в БД.


Именно так и есть. Только дурак будет объяснять юзерам-покуателям недостатки в гуе тем, что "бизнес-слой пришлось бы менять" и "БД такая".
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.