воскресенье, 24 июня 2012 г.

Передача данных с iPad на ПК. Предпосылки

Хороший вопрос возник: как осуществлять связь iPad и персонального компьютера? Но это я забегаю вперед. Задача стоит более конкретная и насущная.

Я собираюсь использовать планшет как инструмент для создания некоторых документов (текстовых в особенности),которые предполагается направлять на печать. Современное состояние техники в нашей стране таково, что направить на печать документ с планшета не представляется возможным. Да это и не нужно: возникнет необходимость его видоизменить, подогнать к нужному формату, и уже после направить на печать.

Так вот. На планшете планирует делать набросок, черновой вариант. Этот черновой вариант далее должен попасть в ПК. Вариант прямого подключения к компьютеру, работающему под управлением Windows, скорее окажется непродуктивным: планшет не будет распознан как накопитель (привет, эппл), с которого файл может быть скопирован. Вероятно также, что на персоналке не будет установлен iTunes. То есть, налицо сложность.

Хорошо. Имеется также мобильный телефон фирмы Nokia. Можно ли передать черновой вариант документа на телефон по, например, Bluetooth? Оказывается и такой возможности не имеется (привет, эппл, еще раз). Если бы такая возможность имелась, то с подключенного к ПК телефона извлечь документ не составило бы труда. Но увы.

Доступен еще один способ: передача данных по беспроводной сети Wi-Fi. Но в этом случае необходима точка доступа и два обменивающихся устройства. Но часто точки доступа может не оказаться. Положение бы спасла возможность телефона становиться точкой доступа и устройством-получателем данных. Тогда на планшете средствами определенных программ имелась бы возможность создавать FTP или HTTP сервер, к которому подключался бы телефон и загружал необходимые файлы.

В общем, вопрос требует дальнейшей проработки.

среда, 14 марта 2012 г.

Взгляд на ООП

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

Эта заметка призвана закрепить то немногое, что я повторно присмотрел и переварил об объектно-ориентированном программировании (ООП).

Переосмысление возникло не на пустом месте, а было вызвано недовольством ООП. Меня постоянно что-то подначивало, заставляло сомневаться в ООП, в его месте в моей практике. Собственно, это было тягучее чувство, что ООП как-то совсем не моё и не может являться базой для получение определённого удовлетворения от разработки программ.

Короче, на определённом этапе недовольство ООП достигло критической точки.

Что же это я всё ООП да ООП. У него есть вполне конкретный образ - Си++, если ещё конкретнее, то Qt.

С чем я для себя сравниваю этот образ ООП - с Си, с одной стороны, с Scheme, с другой. Первый - процедурный язык, второй - функциональный. То есть ни первый, ни второй не является объектно-ориентированным языком.

Что объединяет упомянутые Си и схему? Концептуально? Данные и функции в них разделены. Они существуют по отдельности: есть данные и есть функции.

Что в случае ООП? Функции (в его терминах, методы) определены (существуют) для конкретных данных (экземпляра класса/структуры). Методы и данные неотделимы. Да, они могут существовать как-бы отдельно, но тогда это не ООП в том смысле, что за бортом оказываются свойства, которые дают ООП интересные (мягко говоря) возможности.

Что за свойства? 1) Полиморфизм. 2) Инкапсуляция. 3) Наследование. Первое и второе свойства не так интересны как третье, которое является, на мой взгляд, самым главным.

Наследование. Если к наследованию “прибавить” такое качество как неотделимость методов от данных, то получается, что наследование даёт безграничные возможности по расширению свойств некоторой (базовой) сущности (в смысле данных) и определению дополнительных и ПЕРЕОПРЕДЕЛЕНИЮ существующих методов исходной (базовой) сущности.

Переопределение методов. Почему это важно? Думаю вот почему. При разработке чего-то большого на Си (или функциональных языках) появляется необходимость изменения структуры программы таким образом, чтобы некоторые функции принимали в качестве аргумента другую функцию. Такая возможность, вообще-то, существенно помогает, а часто незаменима. В Си это указатель на функцию с известной сигнатурой, а в схеме всё есть функция, и проблем нет по определению.

Что в Си++? Можно изгаляться и пробрасывать внутрь одного класса указатель на функцию (внимание) экземпляра другого класса. Но на каждый чих делать это не захочется.

В Си++ подход другой. Использует этот другой подход механизм наследования: а) определяется базовый класс с некоторым виртуальным методом (сигнатурой); б) определяется другой класс, который определяется как производный от базового класса, внутри которого кодируется реализация виртуального метода; в) в третьем классе создаётся метод, среди аргументов которого будет указатель на экземпляр класса п.а) для того, чтобы вызвать описанный классом п.а) метод.

Какой вывод? В Си++ (вернее в ООП) сложнее. Конкретно на этом примере.

В Qt с этим проще, потому что существует система сигналов/слотов. Как-бы внешний механизм, который регистрирует и обслуживает вызовы определённых методов, закреплённых за конкретными экземплярами объектов. Более того, этот механизм позволяет осуществлять передачу управления другому потоку (вернее, инициировать вызов метода тем потоком, которому принадлежит экземпляр-владелец метода).

То есть в Qt существует очень эффективный способ “передачи указателя на функцию” для связи двух (в простейшем случае) экземпляров разных объектов (классов). И это хорошо.

Теперь нужно ещё раз подумать и сформулировать в каких случаях применять наследование?

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

Для себя я уяснил следующее: языку свойственны ограничения; их необходимо принять и одновременно забыть об особенностях и ограничениях других языков; способы решения задач средствами языка А отличаются от способов решения тех же задач средствами языка Б.


суббота, 21 мая 2011 г.

Про русскую интеллигенцию

Наша интеллигенция, поголовно почти стремящаяся к коллективизму, к возможной соборности человеческого существования, по своему укладу представляет собою нечто антисоборное, антиколлективистическое, ибо несет в себе разъединяющее начало героического самоутверждения. Герой есть до некоторой степени сверхчеловек, становящийся по отношению к ближним своим в горделивую и вызывающую позу спасителя, и при всем своем стремлении к демократизму интеллигенция есть лишь особая разновидность сословного аристократизма, надменно противопоставляющая себя "обывателям". Кто жил в интеллигентских кругах, хорошо знает это высокомерие и самомнение, сознание своей непогрешимости, и пренебрежение к инакомыслящим, и этот отвлеченный догматизм, в который отливается здесь всякое учение.

Сергей Булгаков

понедельник, 20 сентября 2010 г.

Скролл для блока

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

воскресенье, 12 сентября 2010 г.

Модель предметной области TODO-менеджера

Как следствие вот этого.
Собственно задачи (просто идентификатор и содержимое): T(odos) = ID x CONTENT, где ID = Int, CONTENT = String.
То есть, forall t in T: t = (id, content), id in ID, content in CONTENT.
Отложенные задачи (это так называемый стек задач - общая куча перспективных дел): D(eferred) = T x {0,1}.
forall d in D: d = (t, 0|1).
Завершённые задачи (задача завершена, если 1 + указывается время, когда она таковой стала): C(omplited) = T x {0,1} x TIME, TIME - время.
forall c in C: c = (t, 0|1, time).
Запомненные (задачи описываются крайней датой, наступление которой трактуется как deadline): R(emember) = T x {0,1} x TIME
forall r in R: r = (t, 0|1, time).

воскресенье, 8 августа 2010 г.

Вопросы по C++, ответы на которые нужно знать

Перечень вопросов здесь.
1. How do you check whether a linked list is circular?
Про связные списки бегло читать на википедии.
Реализацию односвязного списка средствами C++ можно наблюдать, например, вот тут. Новые элементы добавляются в начало списка.
Сначала отступление и лирика. Какой список содержит циклы? Тот, в котором присутствуют повторения элементов. Поэтому, список не содержит циклы, если в нём присутствуют уникальные элементы (если что - вопрос не об этом :)).
Решение нуль: сформировать std::set из элементов связного списка; если размер сформированного std::set меньше чем размер связного списка, то в списке существуют циклы, число которых равно разности размеров списка и множества std::set.
Решение про цикличный связный список: список является цикличным если его первый элемент соответствует элементу, следующему за последним (определение); поэтому, нужно перейти к последнему элементу и сравнить головной_элемент списка списка с последний_элемент->следующий_элемент.

2. How do you decide which integer type to use?
Про типы можно почитать здесь.
Ответ: выбор целочисленного типа определяется прикладной задачей, решаемой в рамках данной предметной области; первое - это ширина коридора принимаемых значений переменной целочисленного типа (char, short, int, long; с использованием модификаторов signed, unsigned), второе - количество памяти, отводимое под переменную соответствующего типа (8, 16, 32 бита).