OOPと手続き型プログラミングの比較 - ページ 10

 
Реter Konow:
はい、このユニットにはその両方があります。でも、信じてください。彼らは最大まで圧縮され、幅広い問題を解決してくれるから、汎用性があるのです。

選択肢が少ない場合は、ifとswipeでなんとかなる。

 

なぜ誰も「関数ポインタを使った手続き型プログラミング vs. 関数ポインタを使わない手続き型プログラミング」について議論しようと思わないのでしょうか?

 
Dmitry Fedoseev:

選択肢が少ない場合は、ifとswipeでなんとかなる。

ポイントは、膨大な数のタスクの解をコードで圧縮する作業にある。この問題は、コードの普遍化に関するもので、追加の構文やシェルは単に破壊的なものである。大変な作業ですが、余計なものを排除し、常に新たな高みを目指して進化していくことができます。
 

Реter Konow:
1. Дело в работе которую нужно провести чтобы сжать в коде решения огромного количества задач.

2.ポイントはコードの普遍化であり、そのためには構文技術やシェルを追加することは単に破壊的でしかない。大変な作業ですが、余計なものを排除し、常に新たな高みへと進化させることができます。


1.簡単でシンプルにできるのに、なぜ仕事をするのか?簡単にできるのに、なぜ難しくするのか?

2.OOPを 使えば、普遍化は破壊的なものではなく、何にも負担をかけない自然な可能性になるのです。

 
Dmitry Fedoseev:

1.簡単にできる仕事なのに、なぜやるのか?簡単にできることを、なぜ難しいことをするのか。

2.OOPを 使えば、普遍化は破滅的なものではなく、何にも負担をかけない自然な可能性になります。

この議論は長く続けられる。100トレールタスクを例に、この解法に対する姿勢を示しました。私は、愚かな仕事は解決するのではなく、修正するものだと考えています。もしOOPが、課題を正しく提起し解決することに弱い人たちを助けるのであれば、それはそれでいいのです。しかし、課題を解決する前に最適化する人にとっては、OOPは必要ないのかもしれません。

 
Реter Konow:

この議論は何度でもできる。100トレールタスクを例に、この解法に対する姿勢を示しました。私は、愚かな仕事は解決するのではなく、修正するものだと考えています。もしOOPが、課題を正しく設定し、それを効果的に解決することに弱い人たちを助けるのであれば、これからも助けてあげてください。しかし、課題を解決する前に最適化する人にとっては、OOPは必要ないのかもしれません。


あなたはあまりコーディングしたことがないでしょう(たぶん)、OOPは息を吹きかけるようなものです。

ほとんどの人は、興味や自己啓発のためにコーディングするのではなく、仕事だから、結果が大事なのです。

 
Dmitry Fedoseev:

便利さには遠く及びませんが、スピード性能という点では、ポインタだけでも十分やっていけます。

そして、利便性というのは相対的な概念です。


ドミトリー もちろん、OOPを使うと 性能は少し落ちます。しかし、それは端数である。

しかし、OOPがどのようにプログラマーのパフォーマンスを向上させるのか!

これは私のプロジェクトからの小さな例で、知覚のためにカットされていますが、実際には他の多くの事柄が考慮されています。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

例えば、.NETを例にとると、すべてのAPIはクラスで構成されています。

私は、.NETのパラダイムがとても好きです。 ちなみに、cAlgoという素晴らしい端末があり、Visual StudioでC#で直接書くことができます

 
Alexey Volchanskiy:

ディミトリ もちろん、OOPを使うと 性能は少し落ちます。しかし、それは端数である。

バリエーションが少なければ遅くなるが、多ければ有利になる。

最も重要なことは、OOPではバリアントの数は性能に影響しないということです。そして、手続き型プログラミングでは、頭の上に天井があるのです。

 

まあ、散々な目に遭わされたわけですが...。

インタフェースの割り当て、継承階層の構築、仮想関数の 宣言といったOOPスタイルと、すべてを1つの巨大な関数に集約する純粋な手続きスタイルの両方で、どんなタスクも解決できることは明らかです。

問題は、サポートの利便性と効率性にあります。

MTの場合 - 最もOOPに適した場所は、オーダーシステムです。個人的には、「位置」と「位置成分」の仮想インターフェイスを持っています。"ポジション "は、MT4では注文のセット、MT5ではポジションのセットです。「ポジションコンポーネント」とは、個別の注文または個別の MT5 ポジション(ヘッジまたはネッティング)です。

実際のインターフェイスファイルはこちら(リタグコノウ、コードの量に比べてコメントの数が多いのがおわかりいただけると思いますが、覚えていない微妙な部分に遭遇したときに、定期的にそこに追加しています)。例えば、どの実体が「位置成分」にあたるのか、日頃から忘れてしまっています。Expert Advisorはインターフェースに従ってコンポーネントを操作するので、現実にはそのインターフェースの背後にあるものは重要ではありません。しかし、私は修正中にそれに戻る必要があります - それが、このファイルの最初のコメントが非常に頻繁に必要な理由です)。

// СTradePositionI переносимый интерфейс торговой позиции 

// Позиция состоит из компонент-наследников интерфейса CTradePosComponentI
// 
// Реально для МТ4 имплементацией интерфейса является объект CMT4PositionInfo, для МТ5 - объект CMT5PositionInfo
// CMT4PositionInfo представляет из себя массив объектов CMT4OrderInfo, наследников интерфейса CTradePosComponentI.
// Фактически это массив МТ4-ордеров.
// CMT5PositionInfo представляет из себя массив объектов CMT5PositionInfoCore, наследников интерфейса CTradePosComponentI.
// Объект CMT5PositionInfoCore не имеет прямого аналога в МТ5-терминах, это два массива ордеров и сделок, а также структура данных,
// имеющуая идентификатор позиции (m_lPosID или POSITION_IDENTIFIER), тикет магик, вид позиции, и так далее, по аналогии с МТ4-ордером,
// фактически, массивы ордеров и сделок - это аналоги ордеров и сделок обычной неттинговой МТ5-позиции, а структура данных - относится
// к хеджевой позиции, и имеет аналог МТ4-ордера. 
//
// Реально при запросе у позиции компоненты CTradePosComponentI в МТ4 мы получаем указатель на ордер (класс CMT4OrderInfo),
// а в МТ5 - на ядро позиции (класс CMT5PositionInfoCore) 



#include <MyLib\DebugOrRelease\DebugSupport.mqh>
#include <MyLib\Common\MyObject.mqh>
#include <MyLib\Common\CurSymEnum.mq5>
#include <MyLib\Common\TrendEnums.mqh>
#include <MyLib\Trade\TradePosComponentI.mqh>

class CTradePositionI: public CMyObject
{
public:
   void CTradePositionI() {    SetMyObjectType(MOT_TRADE_POSITION_I); };
   virtual void ~CTradePositionI() {};
   
   // Выбор существующей позиции. 
   // Указывается магик и символ, по которому выбираются действующие ордера.
   // Если ulMagic = 0 - выбираются все позиции по всем магикам.
   // Если ECurrencySymbol = CS_UNKNOWN - выбираются все позиции по всем символам
   // Если ECurrencySymbol = CS_CURRENT - запрашивается функция Symbol(), и выбираются все позиции по этому символу
   // Возвращает число компонент позиции внутри позиции (может быть нулевым если позиции нет) или WRONG_VALUE в случае ошибок
   // Каждая фабрика (наследник CEAPartsFactoryT) имеет одну позицию, которая на каждом CEAPartsFactoryT::OnRefresh()
   // обновляется в соответствии с магиком и рабочим символом фабрики. 
   virtual int Select(ulong ulMagic = 0,ECurrencySymbol csSymbol = CS_CURRENT) = 0;

   virtual uint GetTotalComponents() const = 0;  // Получение общего числа компонент
   virtual uint GetNumOfComponentsOnDirection(ENUM_POSITION_TYPE etDirection) const = 0; // Получение числа компонент указанного направления (если tdDirection = TD_FLAT - то всех компонент)  и интерфейс отдельной компоненты
   virtual CTradePosComponentI* GetComponent(uint uiComponentIdx) const = 0;
   
   // Расширенный интерфейс
   
   // Функция исследует позицию, и возвращает ее направление:
   // Если все компоненты - лонги, то вверх.
   // Если все компоненты - шорты, то вниз.
   // Если компонент нет - то флет. 
   // Если компоненты обоих типов, то смотрим на флаг bFlatIfBoth. 
   // Если этот флаг установлен - то возвращаем флет.
   // Если этот флаг сброшен - то смотрим на флаг bConsiderVolume.
   // Если этот флаг установлен - то сравниваем общие объемы лонгов и шортов. Если сброшен - сравниваем количество лонгов и шортов.
   // Каких позиций (или объемов) больше - то направление и возвращаем. 
   // Если позиций (или объемов) одинаково - возвращаем флет.
   // NOTE !!! Функция не проверяет магик и символ компонент !
   virtual ETrendDirection GetDirection(bool bFlatIfBoth = true,bool bConsiderVolume = true) const = 0;
   
   // Функция ищет внутри позиции компоненту с указанным тикетом. 
   // В случае, если ее нет - возвращается false.
   // Если компонента найдена - возвращается true, и uiComponentIdx устанавливается на индекс компоненты внутри позиции.
   virtual bool FindComponentByTicket(long lTicket,uint &uiComponentIdx) const = 0;
};

トレードコンポーネントインターフェイスのファイルは以下の通りです(上記で既にあげていますが、繰り返します)。

// СTradePositionComponentI переносимый интерфейс компоненты торговой позиции 

#include <MyLib\DebugOrRelease\DebugSupport.mqh>
#include <MyLib\Common\MyObject.mqh>
#include <MyLib\Common\CurSymEnum.mq5>
#include <MyLib\Common\EnumsMT5ForMT4.mqh>

// CTradePosComponentI - компонента позиции. Имеет определенный магик, определенный символ, определенный тикет.  
// Для МТ4 компонента позиции - это МТ4-ордер.
// Для МТ5 компонента позиции - это МТ5-позиция (одна для каждого символа при неттинге, и много для каждого символа при хедже).

class CTradePosComponentI: public CMyObject
{
public:
   void CTradePosComponentI() {    SetMyObjectType(MOT_TRADEPOS_COMPONENT_I); };
   virtual void ~CTradePosComponentI() {};
   
   // Основной интерфейс
   virtual long               GetTPCTicket()       const = 0;
   virtual long               GetTPCMagic()        const = 0;
   virtual ECurrencySymbol    GetTPCSymbol()       const = 0;
   virtual ENUM_POSITION_TYPE GetTPCType()         const = 0;
   virtual datetime           GetTPCOpenTime()     const = 0;
   virtual double             GetTPCVolume()       const = 0;
   virtual double             GetTPCOpenPrice()    const = 0;
   virtual double             GetTPCStopLoss()     const = 0;
   virtual double             GetTPCTakeProfit()   const = 0;
   virtual string             GetTPCCommentary()   const = 0;
   
   virtual bool               IsTPCInUnloss() const { if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE) return(false); if(GetTPCType() == POSITION_TYPE_BUY) { if(GetTPCStopLoss() >= GetTPCOpenPrice()) return(true); } else { if(GetTPCStopLoss() <= GetTPCOpenPrice())return(true); }; return (false); };
   virtual double             GetTPDistance() const { if(GetTPCTakeProfit() == 0 || GetTPCTakeProfit() == EMPTY_VALUE) return(EMPTY_VALUE); if(GetTPCType() == POSITION_TYPE_BUY) return(GetTPCTakeProfit() - GetTPCOpenPrice()); return(GetTPCOpenPrice() - GetTPCTakeProfit());  };
   virtual double             GetSLDistance() const { if(GetTPCStopLoss() == 0 || GetTPCStopLoss() == EMPTY_VALUE) return(EMPTY_VALUE); if(GetTPCType() == POSITION_TYPE_BUY) return(GetTPCOpenPrice()- GetTPCStopLoss()); return(GetTPCStopLoss() - GetTPCOpenPrice());  };
};

class CHistoryPosComponentI: public CTradePosComponentI
{
public:
   void CHistoryPosComponentI() {    SetMyObjectType(MOT_HISTORYPOS_COMPONENT_I); };
   virtual void ~CHistoryPosComponentI() {};

   virtual datetime           GetTPCCloseTime()    const = 0;
   virtual double             GetTPCClosePrice()   const = 0;
   virtual double             GetTPCProfit()       const = 0;  // Возвращает профит по исторической позиции
   
   virtual bool               IsProfitClosePrice() const = 0;   // Возвращает true, если цена зарытия отличается от цены открытия в прибыльную сторону   
   
   // Возвращает профит исторической позиции для случая, когда бы ход цены (в сторону профита) был бы равен dPriceMove, а лот был бы единичным.
   // Функция используется для расчета лота для такой же позиции с нужным ходом цены 
   // Рекомендуется отнимать от цены двойной спред.
   virtual double             CalculateOneLotProfit(double dPriceMove) const = 0;  
  
};

これらのインターフェイスに従って、私はMT4とMT5の両方の注文システムをリアルとヒストリカル両方の注文に実装しています。

ポジションを要求するExpert Advisorは、このインターフェースを受け取るため、MT4とMT5の注文の違いを考慮する必要はありません。また、新しい注文タイプが追加されたり、それらを扱う順序が変更されたりしても、エキスパートアドバイザーは何も変わらず、新しい注文タイプクラスだけが追加され、このインターフェースもサポートされます。

ヘッジ会計が導入されたとき、このシステムは非常に理にかなっていた。専門家は全く変わっていない。

Reg Konow さん、MT4とMT5で注文の種類が違うのは、どのように対処しているのでしょうか?

新しい勘定科目が導入された場合(ヘッジとネッティングに加え)、同じ場所でどのような変更が必要ですか?

私の考えでは、もしあなたが自分のコードを全部覚えていて、その中のこの行やこの行はなぜ1年前に書かれたものなのかが簡単にわかるのであれば、OOP拡張機能はすべて不要なジェスチャーに過ぎないというのが本当のところです。

OOPは、コードを修正する際にすべてを覚えていない場合にこそ必要です。OOPでは、ブロックを互いに分離し、任意の瞬間に利用できるエンティティ群をプログラム内の特定の場所に限定することができます。

 
George Merts:

まあ、散々な目に遭わされたわけですが...。

1.インタフェースの割り当て、継承階層の構築、仮想関数の 宣言といったOOPスタイルでも、すべてを1つの巨大な関数にまとめることができる純粋な手続き型でも、どんなタスクでも解決できることは明らかです。

問題は、サポートの利便性と効率性にあります。

2.MTの場合 - 最もOOPに適した場所は、オーダーシステムです。個人的には、仮想インターフェース「ポジション」と「ポジションコンポーネント」を持っています。"ポジション "は、MT4では注文のセット、MT5ではポジションのセットです。「ポジション・コンポーネント」とは、個別の注文または個別の MT5 ポジション(ヘッジまたはネッティング)です。

3.実際のインターフェースファイルはこちらです(リタグコノウ、コード量に比べてコメントの多さがお分かりいただけると思いますが、微妙に覚えていないことに遭遇すると定期的にそこに追記しています)。例えば、どの実体が「位置成分」にあたるのか、日頃から忘れてしまっています。Expert Advisorはインターフェースに従ってコンポーネントを操作するので、現実にはそのインターフェースの背後にあるものは重要ではありません。しかし、私は修正中にそれに戻る必要があります - それが、このファイルの最初のコメントが非常に頻繁に必要な理由です)。

トレードコンポーネントインターフェイスのファイルは以下の通りです(上記で既にあげていますが、繰り返します)。

これらのインターフェイスに従って、私はMT4とMT5の両方の注文システムをリアルとヒストリカル両方の注文に実装しています。

ポジションを要求するExpert Advisorは、このインターフェースを受け取るため、MT4とMT5の注文の違いを考慮する必要はありません。また、新しい注文タイプが追加されたり、それらを扱う順序が変更されたりしても、エキスパートアドバイザーは何も変わらず、新しい注文タイプが追加されるだけで、このインターフェースもサポートされます。

ヘッジ会計を導入したところ、非常に合理的なシステムであることがわかった。専門家はそこから全く変わっていない。

4.Reg Konow さん、MT4とMT5で注文の種類が違うのは、どのように対処しているのでしょうか?

新しい勘定科目が導入された場合(ヘッジとネッティングに加え)、同じ場所でどのような変更が必要ですか?

もし、あなたが自分のコードをすべて記憶していて、1年前のコードになぜこの行が書かれたのかが簡単にわかるのであれば、これらのOOP拡張機能は不要なジェスチャーに過ぎないと思います。

OOPは、コードを修正する際にすべてを覚えていない場合にこそ必要です。OOPでは、ブロックを互いに分離して、任意の瞬間に利用できるエンティティ群をプログラム内の特定の場所に限定することができます。

1.1.全く同感です。違いは、課題を解決するための有効性を一通り備えているかどうかだけです。

2.私は、受注システムを実際に操作したことはありませんが、その構造上の技術的な問題は見当たりません。でも、具体的な課題があれば、OOPを使わずにどれだけ効率的に解決できるかがわかると思います。

3.私の目から見ると、与えられたコードサンプルは、読みやすさの点から見てひどいとしか言いようがありません。多くのコメントが必要で、なぜその内容を忘れてしまうのか不思議でなりません。申し訳ありませんが、私の主観的な第一印象です。ただただ不気味です。

ここでは、私のコードの読みやすさの例として、コントロールのアイテムの色を定義する関数を紹介します。

int Цвет_детали(int Окно, int Деталь_полотна, int Ячейка_состояния, int GAC = 0)
{
 int Alfa;
 int Цвет_детали;
 int Конечный_цвет;
 int Непрозрачность_детали;
 //--------------------------------------------------------------------------
 int Элемент                     =  G_CORE[Окно][Деталь_полотна][_MAIN_ELEMENT];
 int Состояние_детали            =  G_CORE[Окно][Элемент][_CURRENT_STATE]; 
 int Категория_детали            =  G_CORE[Окно][Деталь_полотна][_OBJECT_CATEGORY];
 int Подкатегория_детали         =  G_CORE[Окно][Деталь_полотна][_OBJECT_SUBCATEGORY];
 int Составной_элемент           =  G_CORE[Окно][Деталь_полотна][_OBJECT_IN_ELEMENT_NUMBER];
 int Тип_элемента                =  G_CORE[Окно][Деталь_полотна][_OBJECT_GROUP];
 int Тип_детали                  =  G_CORE[Окно][Деталь_полотна][_SUB_ELEMENT_GROUP];
 int Элемент_под_курсором        =  G_CORE[Окно][Элемент]       [_ELEMENT_POINTED];
 int Состояние_элемента          =  G_CORE[Окно][Элемент]       [_CURRENT_STATE];
 int Пиксель_детали              =  G_CORE[Окно][Деталь_полотна][_PIXEL_INDEX];
 int Канвас_детали               =  G_CORE[Окно][Деталь_полотна][_DROWING_CANVAS];
 int Пиксель_канваса_детали      =  G_CORE[Окно][Канвас_детали][_PIXEL_INDEX];
 int Состояние_канваса_детали    =  G_CORE[Окно][Канвас_детали][_CURRENT_STATE];
 int Ячейка_состояния_канваса    =  G_CORE[Окно][Канвас_детали][_NEUTRAL_STATE];
 //-------------------------------------
 int Цвет_пикселя_канваса_детали =  STANDART_GROUPS[Ячейка_состояния_канваса + 3 + Пиксель_канваса_детали*2];
 //-------------------------------------
 if(
       (Состояние_элемента == _NEUTRAL_BLOCKED || Состояние_элемента == _ACTIVATED_BLOCKED)
    && (Тип_элемента == BUTTON || Тип_элемента == TB_BUTTON || Тип_элемента == H_TAB || Тип_элемента == V_TAB || Тип_элемента == VIEW_BOX) 
   )
   {
    if(Тип_детали != _VIEW_BOX_VR_SCROLL_BAR && Тип_детали != _VIEW_BOX_HR_SCROLL_BAR)
      {
       Alfa = 255 + GAC;
       if(Alfa < 0)Alfa = 0;      
       return(ColorToARGB(Цвет_пикселя_канваса_детали,Alfa));
      }
    if(Тип_детали == _VIEW_BOX_VR_SCROLL_BAR || Тип_детали == _VIEW_BOX_HR_SCROLL_BAR)
      {
       Alfa = 255 + GAC;
       if(Alfa < 0)Alfa = 0;        
       return(ColorToARGB(clrLightGray,Alfa));
      }   
   }
 //-------------------------------------
 if(!Состояние_элемента)Состояние_элемента = _NEUTRAL_STATE;
 //-------------------------------------
 int Цвет_пикселя           = Данные_пикселя[Пиксель_детали][Цвет];
 int Непрозрачность_пикселя = Данные_пикселя[Пиксель_детали][Непрозрачность];
 //-------------------------------------
 if(G_CORE[Окно][Деталь_полотна][_CUSTOM_BACKGROUND_COLOR]  && Состояние_элемента == _NEUTRAL_STATE) 
   {
    Цвет_детали = G_CORE[Окно][Деталь_полотна][_CUSTOM_BACKGROUND_COLOR];
   } 
 //-------------------------------------
 if(!G_CORE[Окно][Деталь_полотна][_CUSTOM_BACKGROUND_COLOR] || Состояние_элемента != _NEUTRAL_STATE) 
   {
    Цвет_детали = Данные_пикселя[Пиксель_детали][Цвет];
   } 
 //-------------------------------
 if(G_CORE[Окно][Деталь_полотна][_ELEMENT_POINTED]) 
   {
    if(
          (ТИП_ЭЛЕМЕНТА ==  C_HEADER && МЕНЯЕМАЯ_ШИРИНА_СТОЛБЦОВ) 
       || (((Тип_элемента == _C_CELL || Тип_элемента == _D_CELL)   && G_CORE[Окно][Деталь_полотна][_R_HEADER] == РЯД_В_ФОКУСЕ) && ТАБЛИЦА_ИНТЕРАКТИВНА)
       || ((Тип_элемента == _CELL    || Тип_элемента ==  R_HEADER) && ТАБЛИЦА_ИНТЕРАКТИВНА)
      )
      { if(Тип_элемента == _C_CELL && ТАБЛИЦА_ИНТЕРАКТИВНА)Alert(__FUNCTION__,"  Деталь_полотна   ",Деталь_полотна);
       Цвет_детали = C'210,224,237';
      }
    //------------------------------------------------
    if(ТИП_ЭЛЕМЕНТА == _SIMPLE_BUTTON)if(Состояние_элемента == _NEUTRAL_STATE)Цвет_детали = C'250,250,250';
    //------------------------------------------------ 
    if(ТИП_ЭЛЕМЕНТА == TS_BUTTON)
      {
       Цвет_детали =  C'210,224,237';
       Непрозрачность_детали = 100;
       Alfa = Непрозрачность_детали + GAC;
       if(Alfa < 0)Alfa = 0;    
       Конечный_цвет = ColorToARGB(Цвет_детали,Alfa);
       //--------------------------------------------------------------------------
       return(Конечный_цвет);
      } 
    //------------------------------------------------  
    if(Тип_элемента == M_CHECKBOX)
      {
       Цвет_детали = C'210,224,237';
      }
    //------------------------------------------------ 
   }    
 //--------------------------------------------------------------------------
 if(!G_CORE[Окно][Деталь_полотна][_CUSTOM_BACKGROUND_TRANSPERANCY]) Непрозрачность_детали = Данные_пикселя[Пиксель_детали][Непрозрачность];
 else Непрозрачность_детали = G_CORE[Окно][Деталь_полотна][_CUSTOM_BACKGROUND_TRANSPERANCY];
 //--------------------------------------------------------------------------
 if(
       Тип_детали == CHECKBOX 
    || Тип_детали == RADIO_BUTTON 
    || Тип_детали == DROP_LIST 
    || Тип_детали == EDIT_BOX 
    || Тип_детали == SPIN_EDIT 
    // 
    ||((/*Тип_детали == TV_ITEM ||*/ Тип_детали == TV_CHECKBOX
    || Тип_детали == G_FOLDER
    || Тип_детали == TV_MENU)  && (Составной_элемент == BASE_SUB_ELEMENT || (Составной_элемент == BASE_SUB_ELEMENT_2 && Состояние_детали != _ACTIVATED_HIGHLIGHTED && Состояние_детали != _NEUTRAL_HIGHLIGHTED)))
   )
   {
    Цвет_детали = Цвет_пикселя_канваса_детали;  
    Непрозрачность_детали = 255;
   }
 //--------------------------------------------------------------------------
 //Определение цвета ползунка на различных событиях.
 //--------------------------------------------------------------------------
 if(Категория_детали == _SCROLL_BAR_HANDLE && ((КАТЕГОРИЯ_ОБЪЕКТА == _SCROLL_BAR_HANDLE || КАТЕГОРИЯ_ОБЪЕКТА == _SCROLL_BAR || КАТЕГОРИЯ_ОБЪЕКТА == _SCROLL_BAR_BUTTON) || СОБЫТИЕ_ИНТЕРФЕЙСА == _SCROLLER_EVENT))
   {
    if((КАТЕГОРИЯ_ОБЪЕКТА == _SCROLL_BAR_HANDLE && Деталь_полотна == ОБЪЕКТ) || (СОБЫТИЕ_ИНТЕРФЕЙСА == _SCROLLER_EVENT && Подкатегория_детали == _VERTICAL_SCROLL_BAR_HANDLE))
      {
       if(СОБЫТИЕ_ИНТЕРФЕЙСА == _OBJECT_POINTED || СОБЫТИЕ_ИНТЕРФЕЙСА == _OBJECT_RELEASED)      Цвет_детали = C'166,166,166'; 
       if(Ползунковая_прокрутка) Цвет_детали = C'96,96,96'; //|| СОБЫТИЕ_ИНТЕРФЕЙСА == _SCROLLER_EVENT 
      } 
    //--------------------------  
   if(СОБЫТИЕ_ИНТЕРФЕЙСА == _OBJECT_POINTED || СОБЫТИЕ_ИНТЕРФЕЙСА == _OBJECT_RELEASED ||  СОБЫТИЕ_ИНТЕРФЕЙСА == _OBJECT_LEFT_CLICKED || Кнопочная_прокрутка)
      {
       if(КАТЕГОРИЯ_ОБЪЕКТА == _SCROLL_BAR && Деталь_полотна == ОБЪЕКТ + 2)Цвет_детали = C'200,200,200';  
       //-------------------------- && Деталь_полотна == ОБЪЕКТ - 3 && Деталь_полотна == ОБЪЕКТ - 1
       if(
             КАТЕГОРИЯ_ОБЪЕКТА == _SCROLL_BAR_BUTTON 
          && (
               (
                  (ПОДКАТЕГОРИЯ_ОБЪЕКТА == _SBUB && Подкатегория_детали == _VSBH)
               || (ПОДКАТЕГОРИЯ_ОБЪЕКТА == _SBDB && Подкатегория_детали == _VSBH)
               ) 
              ||   
               (
                  (ПОДКАТЕГОРИЯ_ОБЪЕКТА == _SBLB && Подкатегория_детали == _HSBH)
               || (ПОДКАТЕГОРИЯ_ОБЪЕКТА == _SBRB && Подкатегория_детали == _HSBH)
               )               
             )
             
         )
         {//Alert(__FUNCTION__,"  Деталь_полотна   ",Деталь_полотна,"  Непрозрачность_детали   ",Непрозрачность_детали);
          Цвет_детали = C'200,200,200'; 
         } 
      }
    }  
 //--------------------------------------------------------------------------
// 
 Alfa = Непрозрачность_детали + GAC;
 if(Alfa < 0)Alfa = 0;    
 Конечный_цвет = ColorToARGB(Цвет_детали,Alfa);
 //--------------------------------------------------------------------------
 return(Конечный_цвет);
}
//--------------------------------------------------------------------------

ご覧の通り、ここではコメントはほとんど不要です。私のコードはすべてこのスタイルで書かれています。だから、どんな大きさでも完璧に知っているし、覚えているんです。


私の考えでは、あなたの問題解決システムに何らかの欠陥があるのだと思います。問題そのものが明確で正確であるべきであり、それゆえその解決策も明確でなければならない。もし解答が曇り、「システムは非常に合理的であることが証明された」という言葉で定義されるなら(270Kbのコードでどうやって合理的になるんだ!)、それは作者が自分のシステムの仕組みを大まかに理解していることを意味します。そして、その解決策にあるひどい構文の工夫や余分な存在が、彼が最後まで理解するのを妨げているのです。

解決策を講じるには、不必要な存在を切り捨て、問題を完全にクリアに見なければならない。

理由: