> -- Info21 писал(а):
> Это, кстати, добавляет трудности при его освоении и развитии.В надежде на выделение ветки, продолжу в более конструктивном ключе.

Модули, пользующиеся выгрузкой: DevCommanders (командер выгружает модули по Ctrl+Click), DevCompiler (CompileAndUnload) и DevDebug (процедура Unload выгружает модуль из текущего окна; кроме того, здесь же экспортированы UnloadModuleList и UnloadThis). Последние два модуля импортируют первый, что как бы намекает разместить общую процедуру в нём. Однако, логичнее всё же поместить её в DevDebug, так как там у нас концентрируется всё отладочное. Соответственно, предлагаю всего лишь опубликовать существующую процедуру DevDebug.UnloadMod в следующей редакции:
## Код:
```
PROCEDURE UnloadMod* (name: ARRAY OF CHAR; VAR ok: BOOLEAN);
      VAR mod: Kernel.Module; str: Dialog.String; n: Kernel.Name;
   BEGIN
      n := SHORT(name$); mod := Kernel.ThisLoadedMod(n);
      IF mod # NIL THEN
         Dialog.ShowParamStatus("#Dev:Unloading", name, "", "");
         Kernel.UnloadMod(mod);
         IF mod.refcnt < 0 THEN
            Dialog.MapParamString("#Dev:Unloaded", name, "", "", str);
            StdLog.String(str); StdLog.Ln;
            Controls.Relink
         ELSE
            Dialog.ShowParamMsg("#Dev:UnloadingFailed", name, "", "");
            ok := FALSE
         END
      ELSE
         Dialog.ShowParamMsg("#Dev:NotFound", name, "", "");
         ok := FALSE;
      END
   END UnloadMod;
```
Что изменено:
- добавлен маркер экспорта (*);
- параметр name сделан универсальным ARRAY OF CHAR вместо TextMappers.String;
- добавлен вызов Controls.Relink, присутствующий в двух других реализациях выгрузки модуля.

Соответственно, DevCompiler.CompileAndUnload превращается в...:
## Код:
```
PROCEDURE CompileAndUnload*;
      VAR t: TextModels.Model; error: BOOLEAN;
   BEGIN
      Open;
      t := TextViews.FocusText();
      IF t # NIL THEN
         Do(t, StdLog.text, 0, defopt, error);
         IF error THEN DevMarkers.ShowFirstError(t, TextViews.focusOnly)
         ELSE DevDebug.UnloadMod(DevCPT.SelfName$, error)
         END
      ELSE Dialog.ShowMsg("#Dev:NoTextViewFound")
      END;
      Close
   END CompileAndUnload;
```
(В список импорта DevCompiler надо добавить DevDebug.)

DevCommanders не может циклически импортировать DevDebug, поэтому придётся ввести процедурную переменную (при желании - объектный разъём):## Код:
```
UnloadMod*: PROCEDURE (name: ARRAY OF CHAR; VAR ok: BOOLEAN);
```
Инициализировать в DevDebug.BEGIN:## Код:
```
DevCommanders.UnloadMod := UnloadMod;
```

DevCommanders.Unload принять в следующей редакции:
## Код:
```
PROCEDURE Unload (cmd: Dialog.String);
      VAR modname: Kernel.Name; i: INTEGER; ch: CHAR; ok: BOOLEAN;
   BEGIN
      ASSERT(UnloadMod # NIL, 20);
      i := 0; ch := cmd[0];
      WHILE (ch # 0X) & (ch # ".") DO modname[i] := SHORT(ch); INC(i); ch := cmd[i] END;
      modname[i] := 0X;
      UnloadMod(modname$, ok)
   END Unload;
```


В данном решении добавляется только одна новая межмодульная зависимость: DevCompiler -> DevDebug. Если разместить общую процедуру выгрузки в модуле DevCommanders, то новых зависимостей не появится (и не нужен будет разъём), но это представляется нелогичным: кому придёт в голову её там искать? Ещё вариант - создать новый модуль DevUnload, но это, кажется, перебор (хотя, последнее решение подкупает эргономической очевидностью).