вторник, 29 августа 2017 г.

Ссылка. КОМПОЗИЦИЯ ПРОТИВ МЕХАНИЗМА НАСЛЕДОВАНИЯ

https://abraxabra.ru/react.js/bystryy-start/kompozitsiya-protiv-mekhanizma-nasledovaniya/

Процитировав одного знакомого. Надеюсь, что он не будет против:

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

https://plus.google.com/u/0/100903871335644471614/posts/USU25WJA2eh?cfem=1

четверг, 24 августа 2017 г.

Off-topic. Наблюдение

Сегодня на совещании при обсуждении "технических моментов" коллеги "припомнили" (по доброму) мне мои ошибки прошлого. Которые я признал. Я стал говорить "возможно я ошибался" или "возможно я пересмотрел свою позицию" или "возможно я тогда вас не так понял".

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

Хороший вариант. Возможно.

Хотя - я лично сомневаюсь.

Возможно - "спокойнее" и "рассудительнее" (в том смысле, что не тороплюсь принимать решения).

Так - наверное скорее.

Ну и наверное всё же научился "слышать", а не только "слушать".

Возможно.

Но не "умнее". Умнеть в последнее время - что-то не получается.

пятница, 18 августа 2017 г.

ToDo. Сделать Named:

Именованные "анонимные функции":

.filter> Named: n1 ( bla )
.filter> Named: n2 global

Их имя нужно только для отладки и диагностики.

Это можно применять для "именования" post- и pred-условий:

Pre:
 ( x = 1 ?assure 'bla' )
 Named: n1 ( y = 2 ?assure 'bla' )
;

Post:
 ( z = 1 ?assure 'bla' )
 Named: n1 ( i = 2 ?assure 'bla' )
;

Или:

Pre:
 ( x = 1 ?assure 'bla' )
 Условие: n1 ( y1 = 2 ?assure 'bla' )
 Условие: n2 ( y2 = 2 ?assure 'bla' )
 global1
 global2
 Условие: n3 ( y3 = 2 ?assure 'bla' )
 ( x1 = 10 ?assure 'bla' )
;

Или:

До:
 ( x = 1 ?верно 'bla' )
 Условие: n1 ( y1 = 2 ?верно 'bla' )
 Условие: n2 ( y2 = 2 ?верно 'bla' )
 global1
 global2
 Условие: n3 ( y3 = 2 ?верно 'bla' )
 ( x1 = 10 ?верно 'bla' )
;

Или:

Предусловия:
 ( должно: ( x = 1 ) 'bla' )
 Условие: n1 ( должно: ( y1 = 2 ) 'bla' )
 Условие: n2 ( должно: ( y2 = 2 ) 'bla' )
 "Глобальное условие 1"
 "Глобальное условие 2"
 Условие: n3 ( должно: ( y3 = 2 ) 'bla' )
 ( должно: ( x1 = 10 ) 'bla' )
;

До:
 "Очищать тестовую базу" // - это ДО
 "Очищать таблицу стилей"
 "Открыть документ" "Конституция"
;

Параметры:
 "Выливать в RTF"
 "Восстанавливать позицию мыши"
;

Тест:
 "Выделить документ"
 "Заменить" 'а' на 'б'
;

Постусловия:
 "Drag&Drop завершён"
;

После:
  "Закрывать все окна"
 "Очищать тестовую базу" // - это ПОСЛЕ
;

В таком порядке и вызывается:
Предусловия, До, Параметры, Тест, Постусловия, После.

Все секции - опциональны.

Для этого сделать TtfwNamedBeginLike с соответствующим конструктором.

И звать его из Named:, который определить на стороне скриптов.

Не забыть про трансляцию resultType и paramTypes, а также innerDictionary etc.

И прочей инфраструктуры для работы с компилированными словами.

Сделать ещё конструкции:

"В диалоге" "Номер 2 или больше" "Удаление конституции" отвечать Всегда
"В диалоге" "Удаление конституции" отвечать Нет
"В диалоге" "Удаление документа" отвечать Да
"В диалоге" "Поиск/замена" выполнять "Выбор метки"
"Для диалога" "Выход из приложения" "Проверять его отсутствие"
"В диалоге" "Любом другом" отвечать Нет

После слова "В диалоге" предполагаются на самом деле две лямбды:
1. Comparator. Туда передаётся DialogInfo, а возвращается Boolean.
2. Executor.

Comparator и Executor - самом деле могут связываться в цепочки, как в примере про диалог #2.

Предикатов на самом деле просто складываются в список и последовательно выполняются для каждого диалога.

По аналогии с RULES.

Никакого "волшебства".

Это некоторым образом похоже на "предикаты" и "машину вывода" Prolog'а.

Порядок предикатов  - влияет на порядок вычисления предикатов.

Это вместо wait:XXX/waited?

Т.е. делаем "декларативность", а не "императивность".

Мы НЕ ОЖИДАЕМ, диалога, а говорим, что надо делать, если он появился.

Ну и старый "добрый" (на самом деле - бардачный) механизм пока оставляем. Для обратной совместимости.

Возможно для наглядности стоит ещё ввести секцию Диалоги: перед секцией Тест:.

Ещё надо сделать конструкцию:

"Локальные диалоги":
(
Предикат1
Предикат2
Предикат3
...
ПредикатN
)
( код )

предикатов для диалогов действительны ТОЛЬКО для указанного локального кода.

Там две лямбды:
1. Регистрация обработчиков диалогов.
2. Код, приводящие к диалогу.

Ели один из ожидаемых дипломов не показан, то надо поднимать исключение - 'неожиданный диалог'.

Для совместимости со старым кодом.

Собственно с этого и надо начать.

Это больше похоже на текущий механизм.

И это похоже на механизм TF aVar (). Тоже лямбда, обёрнутая в try..finally.

Ещё надо сделать:
PredicatExecutor.
LambdaExecutor.
Etc.

Для удобства работы со словами на стороне Delphi.

В итоге - убрать wait, waited, answer, modal, etc.

А всё свести к modalService и dialogStack.

И написать что-то вроде:

Function modalService.Execute (aForm): TModalResult;

Result := mrCancel;
if dialogStack.Execute(aForm, Result) then
 Exit
else
if TBatchService.IsBatchMode then
 raise EBatchMode.Create('нельзя показывать модальный диалог в пакетном режиме')
else
 Result := aForm.ShowModal;

Слова wait:XXX временно перенести на сторону скриптов, вывести их через wait:Button. А потом их вообще убить.

Потом переделать всё это на Thread. И убрать hackedVCL/needCancelModal.

А потом подобным образом отрефакторить menu.Popup.

Ещё сделать глобальную функцию/примесь для переделки ShowModal и copyPaste "от Димы".

Переделать регистрацию констант mrXXX на RTTI. Ну как TColor и TCursor.

Вообще подумать о регистрации ВСЕХ констант, через RTTI и RegisterIdent.

http://docwiki.embarcadero.com/RADStudio/Seattle/en/Colors_in_the_VCL

Инверсия зависимостей

"Правильнее" было бы делать не:

If theForm.ShowModal ... then

А:

If TModalService.Execute(theForm) ... Then

Это и расширяется и тестируется гораздо гибче.

А вместо:

theMenu.Popup

Лучше:

TPopupService.Execute(theMenu)

или вместо:
theSaveDialog.Execute

Пишем:

TSaveDialogService.Execute(theSaveDialog)

А для сервисов можно сделать:

TModalService.Inject(TmyModalService.Instance)
TPopupService.Inject(TmyPopupService.Instance)
TSaveDialogService.Inject(TmySaveDialogService.Instance)

- иньекция реализации.

Подменяем реализацию сервиса. Например для тестирования.

"Клиенты" сервиса про такую "подмену" - даже не узнают.

Они будут "думать", что вызывают "оригинальный" сервис.

Это всё реализуется либо при генерации из UML либо при помощи Generic'ов.

И например для тестов не показываем диалоги/меню. А зовём mock'и. К примеру.

Подумалось. Про инверсию зависимостей

Вот во времена Turbo Pascal/Turbo Vision у контролов была концепция Validator'ов.
Ввода/вывода.

Очень правильная концепция, как я теперь понимаю.

Жалко что Borland когда сделал Delphi - выпилил эту концепцию.

Тогда бы например не надо было бы "городить" отдельный класс типа TMaskEdit.

А уж теперь при наличии "лямбд".

Приходится прикручивать свой аналог.

Даже VisualLiveBinding - "вроде про то же",  но не "про то".

ToDo

1. Васстановить isSmart на imageList.
2. Сделать imageListService.
3. На сервисах делать обёртки iXXX.
4. Попробовать внедрить imageListService в back, через заплатки.
5. Включить stackFrames для nsTest и insiderTest.
6. Обрабатывать исключения в l3GetFileSize.
7. Стирать diff и sdiff перед сравнением.
8. Assert при поиске diff заменить на  вывод в лог.
9. Расширить Il3ImageList и сделать его интеллектуальную фабрику. На imageListService.
10. Дописывать сервисам суффиксы service и serviceImpl.
11. Сделать сервис для showModal. Реализовать его для тестов.

вторник, 8 августа 2017 г.

ToDo. Сделать outx, varx

Сделать outx, varx:

outx obj: iunknown
varx p: Pointer
varx o: TObject

Перевести на них QueryInterface, FreeMem, FreeAndNil etc. 

ToDo. Сделать для Delphi7 UnicodeString

Сделать для Delphi7 UnicodeString, UnicodeChar.

PUnicodeString, PUnicodeChar.

В l3Core.

А также:

Tl3UnicodeString, Tl3UnicodeChar.

Pl3UnicodeString, Pl3UnicodeChar.

PWinApiChar, PWinApiCharA, PWinApiCharW.

PFileChar, PFileCharA, PFileCharW.

А также - всё что связано с IStream/IStorage. Large,ULarge/PLarge/PULarge/StreamPos/StreamSize/HighStreamPos/HighStreamSize/VoidStreamPos/VoidStreamSize.

В модуль l3XE/Berlin.

Поискать IfDef Berlin.

Сделать стереотип TypeDefProxy. Без вывода в код, но с uc.

Перевести на него Tl3NativeInt/Tl3NativeUInt.

ToDo. Опубликовать в скриптах Pointer

Опубликовать в скриптах Pointer/PMem/PByte/PLong,PInteger,PCardinal,PWord/Pxxx.

PChar/PAnsiChar (?)

Сделать Pointer:Deref/Add/Sub.

Сделать метод .IsPointer.

ToDo. Сделать IsConst/IsAssignable/IsLValue

Сделать IsConst/IsAssignable/IsLValue.

В CONST проверять IsConst.

True/false/nil/null/kwInteger/kwString/tfwInteger/tfwString etc сделать IsConst.

Сделать модификатор CONSTANT.

Для указания того, что слово возвращает КОНСТАНТУ.

BOOLEAN CONSTANT : TRUE true >>> Result ;

На keyword(?)/globalkeyword сделать up - CONSTANT.

Сделать INTEGER CONSTANT IN/ValueAtLeft/ValueAtRight.

Для этого сделать:
 PopValue/SetToDefaultValue.

- чтобы параметры можно было минимизировать со стека и более - НЕ ТРОГАТЬ.

В := и >>> в compile-time проверять IsConst.

ToDo. Сделать ValueAtRight

Сделать ValueAtRight.

ValueAtLeft.

Попробовать на:
Integer:+:

RefAtRight/RefAtLeft.

Попробовать на:
Inc/Dec.

FunctorAtLeft/FunctorAtRight/Functor.

понедельник, 7 августа 2017 г.

суббота, 5 августа 2017 г.

Off-topic. Ремарк

Ремарк...

Ну и конечно "На западном фронте без перемен"/"Im Westen nichts Neues". Это - шедевр. Кровь, грязь, кишки, боль, поход к французским проституткам через линию фронта, снова кровь, грязь, и боль. Консервы. Воронки. Гранаты. Колючая проволока. Пулемёты. Сапоги с мёртвого товарища.

 Ожидание. Смерти. Других. А потом... "он погиб, когда газеты сообщали о затишье, на западном фронте"...

Ну и конечно "время жить и время умирать" и "возлюби ближнего своего".

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

Ну и "три товарища". Уличные бои между нацистами коммунистами.

ToDo. Вывести всё через Less

Сделать <, >, <=, =>, <>, ==, !== производными от Less.

В compile-time.

пятница, 4 августа 2017 г.

ToDo. Сделать [[ и ]]

Сделать [[ и ]].

Типа - константный массив.

[] - пустой массив. Предопределённый. Неконстантный.

[[]] - пустой массив. Предопределённый. Константный. Видимо равен [nil], [empty].

Также сделать:

!( - анонимная функция, без видимости переменных родителя.
:( - анонимная функция с результатом.
:!( - анонимная функция с результатом и без видимости родителя.

Сделать IsConst на TtfwWord. Проверять возможность присваивания.

И вытащить это в compile-time.

Сделать IsFullyDefined - определять, что слово полностью завершено.

Определить его в true для переменных, констант, ->, и слов без параметров, а также для слов у которых полностью захвачен контекст, Capture, !(, :!(, etc.

ToDo. Регистрировать с модели Compare, Add, Sub, ToPrintable, etc.

Регистрировать с модели Compare, Add, Sub, ToPrintable, etc.

А также:

Mul, Div, Mod, Mul2, Div2, >0, <0, =0, etc.

четверг, 3 августа 2017 г.

Хочется чего-то нового

Может кто-то возьмёт меня на аутсорсинг "на обучение".

Типа JS, React, Angular, Python, Groovy, Velocity и всё такое. QT возможно...

Я JS ни хрена не знаю, Qt - тоже, зато знаю Delphi, DUnit, FORTH, C/C++/stl, Objective-C, asm386, asmPDP-11. Ну и про Python - "читал" и представляю себе как их виртуалка устроена. Та же стековая машина и словари ключ-значение. Ну и про MVC - я тоже "слышал". Ну и "функциональщину" я теперь тоже в общем себе представляю.

Про boost и "лямбды" - я тоже где-то слышал.

Знаю чем "сортировка пузырьком" отличается от qsort. Log2(N) vs N*N.

Также слышал про "сортировку слиянием".

Примерно представляю себе разницу между vector, list, set, map.

Понимаю разницу между mutable и immutable объектами.

Имею представление о шаблонах проектирования - publisher/subscriber, command, lightweight, factory, algorythm/strategy, decorator, proxy, facade.

Имею "смутные представления" о Dependency Inversion и Inversion of control.

Также - даже понял как устроены стековые фреймы в x86 и x64.

Примерно представляю себе как получить стек вызова функции.

Знаю, что такое, Pascal, cdecl, register, stdcall.

Примерно понимаю, что такое thread и "защищаемые ресурсы", а также всякие объекты синхронизации - interlockedIncrement/decrement/exchange, criticalSection, mutex, event, waitForSingleObject.

Умею пользоваться CVS/SVN/git. Из gui-клиентов, а не из коммандной строки.

Примерно представляю себе концепцию TDD. Использую её интерпретацию в основной работе.

Основная операционка - Windows. Также работал под xOS.

Про Linux/Unix - "слышал".

Знаком с UML. Использую его и собственную кодогенерацию в основной работе.

Примерно представляю себе как устроен XML/XSLT. А также - json. Но именно - "примерно".

Не то чтобы меня текущая работа не устраивает. Но хочется чего-то нового. На реальных задачах. Тем более, что у Delphi - "смутные перспективы".

На период "обучения" и въезжания в тему - денег особо не надо. А там - как пойдёт.

БД и SQL - я правда ни хрена не знаю. Не занимался такими задачами. Все хранилища были "самопальными".

Работу я пока менять не планирую, но хочется чего-то нового. Другого плана задач. Другой язык и фреймворк. Может быть получится взаимовыгодное сотрудничество.

А то "мозги застаиваются" и квалификация уходит.

Хочется чего-то нового попробовать. Но не хочется "учебные задачи" из пальца высасывать.

На hh.ru и прочих - сознательно не пишу. Ибо это не "поиск работы", а скорее поиск какого-то "симбиоза".

Чтобы я чему-то поучился, ну и в ответ - чего-то дал.

А то кругом BigData и прочие HighLoad'ы а я всё собственные "велосипеды", да "на коленке" делаю.

Хочется пообщаться с людьми из "не своего круга".

Чтобы посмотреть - "а чем там ещё люди занимаются".

Глядишь - и для основной работы польза будет.

Ну и из "спортивного интереса".

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

На вопрос - "тебя мало загружают на работе" - отвечу - "меня много загружают. Более чем". Но всё - единообразно. 20 лет уже как.

Все задачи - "примерно одинаковые". И примерно на одном и том же инструментарии.

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

Off-topic. Займусь самокопанием

Вот так... учишь учишь человека... думаешь, что он от тебя чему-то научился... И даже типа - "вроде благодарен"... А потом слышишь - "нет - ты хреновый капитан"... И не "порть мол других"... :(

Эх...

Всё правильно...

"Вкладываешься" в людей. А они тебе - "хреновый ты капитан".

Одного только не понимают, что они "БЕСПЛАТНО" - научились на МОИХ ошибках, а не на СВОИХ и "за деньги".

Но всё равно - не очень приятно это слышать от тех, кому считал - "отдал всё что мог".

Как говорил Высоцкий - "я ко всем людям иду с открытой душой, и лишь потом - я в них разочаровываюсь".

Но мол - "я не перестаю наступать на одни и те же грабли".

Потому что, мол - "людям всё равно надо верить".

И далеко не каждый "ученик" переросший "учителя" - сможет остаться благодарным.

Я сам - грешен. Хотя в последнее время - перерос это. И даже - "самый гадкий лектор моих ученических времён" - кажется мне теперь "средоточием мудрости".

А так и есть. Просто я "тогда" - не смог "воспринять его". Ну или - "не захотел".

Ну или - "гордыня"...

Я теперь понимаю, что чувствует тренер, когда спортсмен говорит - "у меня был хреновый тренер".