Jack Ferre писал(а):Хакер, я совершенно не знаком со спецификой работы с PKCS11, и исхожу только лишь из задачи поставленной автором топика. У него уже имеются (каким-либо способом) полученные utf-8 строки хранящиеся в переменных String. Вот их то мой класс и принимает.
Это не имеет значение. Проблема находится
по эту сторону класса, а не
по ту.
Речь идёт о том, что твоё понимание правильной методологии проектирования, в частности, создания грамотных интерфейсов, находится на низком уровне. Что там за реализация, что там за библиотека, с которой надо работать — вообще не играет роли.
Jack Ferre писал(а):По поводу функции ВашаФункцияКодированияВUTF8 as String - её можно заменить на ВашаФункцияКодированияВUTF8 As Byte().
Её не нужно заменять. Её нужно засунуть внутрь класса и сделать вообще невидимой снаружи. Это внутренняя работа класса. Это то, что должно быть инкапсулировано в нём и скрыто от стороннего наблюдателя. Если в PKCS11 что-то поменяется, и строки нужно будет слать в другом формате, то все изменения в коде будут ограничены правкой внутри класса. Код за пределами класса
вообще не узнает, что что-то там поменялось. Он как до этого передавал строки в своём родном формате, так и будет в нём передавать.
Jack Ferre писал(а):Но вы видимо не читали весь код в топике и не заметили что я функцией PutByteArray сохраняю данные в переменную (О ужас!) типа String. Связано это с тем, что я не знал (да и сейчас не очень интересно) как извлекать ByteArray из Variant-а и заменил извлечение просто конвертацией CStr.
Интерфейс всегда важнее реализации. Реализация имеет право временно быть плохой, а вот интерфейс не имеет. Если интерфейс спроектирован неидеально — это навсегда. Это проклятие, родовая травма и уродство кода (и проекта вообще). Заложенное в интерфейс уродство будет отражено в тысячи местах кода, где этот интерфейс используется. Поэтому интерфейс не может быть кривым.
Реализация может временно быть плохой. С тех пор, как определён прекрасный интерфейс, другие люди пишут код, который работает с ним. Эти люди не знают и не думают о том, что реализация отвратительна. Даже если они вдруг начинают это замечать, реализация может быть переписана полностью, и это никакого никак не затронет, кроме как тем, что всё станет работать ещё лучше.
Поэтому на проблему с интерфейсом я смотрю более серьёзно, чем на проблемы с реализацией.
Jack Ferre писал(а):Более того при написании класса CCKData я еще не знал, что строки будут в utf-8. После того как узнал, предложил просто добавить "заплатку" в виде PutString ВашаФункцияКодированияВUTF8(CStr(value)).
Ну. До тебя никак не может дойти, в чём твоя фатальная ошибка.
Если бы ты предложил заплатку вставить внутрь класса, это было бы окей. Но ты предложил задействовать её снаружи по отношению к классу.
Это фатальная ошибка.
Если ты не понимаешь, почему это столь критически важно, то это ещё более фатальная твоего твоего самопонимания как программиста. Ничто так не важно, как это.
Jack Ferre писал(а):Более того при написании класса CCKData я еще не знал, что строки будут в utf-8.
Плюс ко всему, именно в этом и фишка: грамотный человек правильно проектирует интерфейс, даже не зная этих вещей. Грамотный человек заранее предвидит, что строки могут понадобиться в какой-нибудь хитрой кодировке. Поэтому правильная позиция: мы не знаем, в каком именно формате понадобятся строки на выходе, поэтому мы намеренно провозглашаем, что на входе строки всегда должны быть в неком общепринятом для нашего контекста формате (а конкретно — UCS-2), а уже внутренности класса сами сконвертируют в то, что нужно.
Jack Ferre писал(а): Пришлось конвертить данные под однобайтовые через StrConv
и сделал вывод, что в строке уже лежит utf-8 в виде "байт-дырка-байт-дырка" (типа Привет => Привет) и никакая заплатка в этом случае не нужна.
Это очень странная манера думать и делать выводы.
Function Умножить_A_на_B(a, b): Умножить_A_на_B = a + b: End Function — эта функция прекрасно выполняет задачу по умножению чисел, ведь для
Умножить_A_на_B(2, 2) возвращает 4, как и следовало бы ожидать.
Вот примерно такова твоя аргументация. ALX_2002 просто попробовал что-то сделать на примере строки, состоящий только из кодовых точек с кодом меньше 127. И о чудо, это был тот частный случай, где что сложение, что умножение даёт одинаковый результат. Ой, прошу прощение, не сложение и умножение, а Ucs2ToCp1251 и Ucs2ToUtf8 дали одинаковый результат.
Jack Ferre писал(а):Итог.
В случае оставления стороны проекта ALX_2002 "как есть":
case vbString - не трогать. Она уже строка. В ней уже лежит массив байт utf-8. Можно добавить StcConv(,vbFromUnicode), чтобы не вызывать его каждый раз на стороне проекта.
case vbArray+vbByte - довести до ума извлечение из Variant-а (если кто-нибудь возьмется), Также можно было бы оставить Cstr (в решение Кривоуса Анатолия с непрерывным массивом копировать данные из полученной строки в массив с помощью CopyMemory), но за это отрывают руки, вкручивают колья и всё такое
.
В случае переделывания стороны проекта ALX_2002 "как надо":
Передавать в класс utf-8 строки в виде массива байт. Переписать класс - не определять, а явно указывать тип данных.
Оба хуже (c)
Я уже не говорю про гадости типа
vbArray+vbByte вместо
vbArray Or vbByte — на фоне прочего они выглядят мелочами.
Передавать в класс строки нужно в обычном привычном для всего остального кода формате. Про UTF8 код, который пользуется классом, знать не должен вообще. Unless UTF8 играет важную в проекте роль независимо от того факта, что библиотека PKCS11 использует UTF8.
Jack Ferre писал(а):На десерт:
[quote=MSDN]BSTR is an OLE automation type for transferring length-prefixed strings, either Unicode or ANSI, as well as length-prefixed binary data.
Тогда я позволю себе напомнить приведённый выше пример насчёт хранения хлеба в унитазе. Некоторые этимологические словари приводят такую этимологию: «
универсальный
таз». А раз таз универсальный, то значит и хлеб там можно хранить, почему нет?
[/quote]