Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Для новичков > Разработка приложений в ОО-стиле |
Автор: EvilsInterrupt 21.4.2009, 14:17 |
Что тревожит: Начать разрабатывать с использованием С++. Пояснение тревоги: Раньше сидел на Delphi и худо бедно привык к ее среде разработки и модели ООА\П. Потом при переходе на С используя MS Visual Studio 2005(8) Team Suite тоже довольно понятно. Процесс разработки упирается в простейшее: - Поиск ответа1 "Что хотим сделать ?" - Поиск ответа2,...,ответ_k "Как достичь ответ1 ?" - После к каждому ответу2 и до ответа_k задаем свои вопросы и получаем для них ответы2_1, ответы2_2 - Повторяем до тех пор пока не получим тривиальные ответы, которые оформляем функции. Получается своего рода алгоритмическое дерево. Одна ф-ция вызывает вторую, вторая третья, ну и разные вариации, хотя местами это не дерево а сетка, т.к. переплетения. + в этом подходе, это то что очень легко написать проверочный код и понять "А так ли я хочу это видеть ?", возможно появится : "млин, это же не совсем то что хочу" и потому можно на ранней стадии разработки увидеть косяк, ну и увидеть результат от которого будет зависеть дальнейшая разработка. ----- Решил на С++, т.к. почитал плюсы ОО-стиля анализа, проектирования и программирования, меня они впечатлили и решил попробовать. Что выходит ? В ОО- стиле, ничего подобного не могу!!! ;( Как возьмусь, так сразу же то одна ошибка, то мне чтото не понравится в классе и методе и если в процедурном всегда легко написать проверочный код и узнать а все ли так как я хочу, то в ОО-стиле надо четко задать конструктор, а это надо сделать инициализацию класса, причем продумать логику его создания, толи он по чтению тогда надо вернуть (I_IStream *) , толи он по записи тогда вернуть (I_OStream *) . Но это еще не все, в конкретике это будет C_FileStream который есть сынок C_IOStream и вот пока два класса не напишешь, ничего не получишь! Все сводится к тому, что результат можно увидеть через громадное количество разработанных методов, т.к. класс не создастся без инициализирующих действий. Вобщем, голова идет кругом, у меня даже желание пропадает, от такого количество сложностей, которые еще не понятно стоит ли преодолевать или это ошибочный путь ? Вопрос темы: Прошу прояснить, как следует подходить к процессу разработки на С++ , чтобы можно видеть маленькие промежуточные результаты, как вообще стоит подходить к разработки ОО-приложений ? Что делаю? 1. Читаю Гради Буча про ООА\П 2. В планах после него читать Фаулера про рефакторинг. ЗЫ: Этот вопрос относится больше всего к философии разработки. Да, не спорю, но мне бы хотелось слышать практический опыт. |
Автор: EvilsInterrupt 22.4.2009, 10:43 |
Лучше будет взять реальную ситуацию и ее обсудить. В-общем, разрабатываю библиотеку по работе с файлом, памятью, сетью в единном стиле написания кода. При процедурном, я бы объявил IO_CONTEXT и функции IO_GetByte, IO_GetWord, IO_GetDWord, IO_SetByte, IO_SetWord, IO_SetDWord, IO_ReadBuf, IO_WriteBuf, IO_Init, IO_Close, IO_Flush, IO_UpdateBuf, ну можете еще какие-нить возле этой темы пробегающие ) Как же пытаюсь напрограммить в ОО-стиле ? 1. Задаю вопрос : "Что будет делать клиентский код? Что ему надо? " - Иметь доступ по чтению - Иметь доступ по Записи - Иметь доступ по чтению или записи Исходя из этого прихожу к концепции стримов и задаю интерфейсы: class I_Stream; // << --- здесь методы Clone, SetSeek общие для всех интерфейсов стримов class I_IStream : public I_Stream; // Возврат байта, ворда, дворда, чтение буфера class I_OStream : public I_Stream; // Установка байта, ворда, дворда, запись буфера class I_IOStream : public I_IOStream; и реализовываю первый абстрактный класс class C_IOStream : public I_IOStream; Дальше спрашиваю себя : "Что конкретно будет юзер писать ?" - Работа с файлами, тогда class C_FileStream : public C_IOStream; - Работа с памятью , тогда class C_MemoryStream : public C_IOStream; - Работа с сетью, тогда class C_NetworkStream : public C_IOStream; Казалось бы все хорошо выглядит, но не удавалось пощупать результат, пока не продумал архитектуру библиотеки! И даже сейчас, я не могу пощупать, т.к. чтобы создать файловый стрим, мне надо реализовать множество методов, пусть даже сделав пустышки(костыли) на время. Мне бы хотелось знать методику разработки ОО-библиотек\приложений, которые бы позволяли сразу же видеть промежуточный результат, т.е. как бы написал клиентский код, посмотрел и спросил себя "А все ли верно?", но вот только как это сделать? ПОка не знаю и не умею, приходится писать и надеяться что все будет так как и надо, что невозникнет потом каких-либо нюансов! Замечу: Программисты давно стараются привлечь методики программирования, чтото заставляют проверять компилятор, чтото компоновщик, а чтото в UML тулзах на согласснованность проверят. Так что не думаю что уместна фраза : "А ты напиши и посмотри", надо как-то более практичный подход или "написал мало, проверил, убедился" вот только как как это "мало написал" ? |
Автор: bsa 22.4.2009, 10:56 |
EvilsInterrupt, зачем ее писать? http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio.html и стандартные потоки http://www.cplusplus.com/reference/iostream/ используй. А разобравшись с ними, у тебя уже меньше вопросов будет возникать по поводу ООП. |
Автор: EvilsInterrupt 22.4.2009, 10:59 |
bsa, Плюс моей библиотеки в том, что потому будет моя собственная библиотека типов! для DWORD, BYTE, WORD . Потому что под Intel один порядок байт,а ты посмотри скажем под спарки или Motola какую нить и вывод, в свою библиотеку я смогу вставить свои типы, а вот чужую смогу,но это надо будет перелопачивать. К тому же маловат еще уровень, чтобы в бусте ковыряться |
Автор: Lazin 22.4.2009, 12:13 | ||||||||||||
boost::asio уже существует ![]()
во первых следует начинать не с интерфейса класса, а с предметной области в данном случае у нас есть набор средств ОС, и средства для взаимодействия с ними это может выглядеть так: есть сущность - Service, некий объект отвечающий за взаимодействие с ОС для разных подсистем могут быть реализованы разные сервисы, к примеру: FileService, TCPService, NamedPipeService, MemoryMappedFileService. есть объект(сущность) Stream, с которым работает пользовательский код. Этот объект должен формировать пользовательский API. К примеру, он может содержать методы GetWord, SetWord, GetByte итд... Далее, должны-быть реализации, к примеру, FileStream, TCPStream, NamedPipeStraem. Каждый из этих объектов не должен работать с объектом ОС напрямую, вместо этого он должен использовать соответствующий сервис. К примеру, FileStream должен использовать FileServcie FileService может быть реализован примерно так
соответственно, у разных сервисов будут разные интерфейсы FileStream может его использовать примерно так:
FileStream должен знать только о FileService, больше ему ничего не нужно, один сервис может работать с множеством Stream объектов соответственно, для всех NamedPipeStram должен быть создан один сервис PipeServcie etc... это позволит разделить интерфейс и реализацию далее, можно провести рефакторинг, например выделить базовый класс для потоков(к примеру IStream) и базовый класс для сервисов, так-же можно создать фабрику объектов для Stream-ов и так далее ![]() в результате это может выглядеть как-то так:
или с помощью фабрики объектов
Соответственно, для другой платформы, тебе потребуется только создать новые сервисы, но не Stream-ы ![]() |
Автор: bsa 22.4.2009, 22:46 | ||
Порядок байт бывает Big endian (прямой) и little endian (обратный). Это тоже в бусте все учтено. Более того, в стандарте Си (не знаю, как в С++) stdint.h, который определяет типы вида uint32_t, sint8_t... Думаю, твои WORD'ы и прочее рядом не стояли... Изучение буста повысит твой уровень на порядок. И если у тебя не чисто академическая задача по написанию библиотеки, то не трать время на нее - на изучение буста ты потратишь гораздо меньше. Да и через пол году будет меньше разочарований: "ну, кто же так пишет?!?" P.S.: но я уверен, что многие здешние корифеи некоторое время назад тоже занимались изобретением велосипедов... Я в том числе. Просто совет - не трать время. |
Автор: J0ker 23.4.2009, 00:06 | ||
и понеслааааааась... ![]() я бы на вашем месте не задевал чувства верующих ![]() Добавлено через 5 минут и 37 секунд ...и middle endian (осторожно, экзотика ![]() |
Автор: J0ker 23.4.2009, 00:27 | ||
правильно - сам себя не похвалишь - никто не похвалит ![]() |
Автор: bsa 23.4.2009, 00:32 | ||
![]() |
Автор: Lazin 23.4.2009, 09:16 |
![]() |
Автор: J0ker 23.4.2009, 16:11 | ||
существует небезосновательное мнение, что интерфейс класса гораздо важней для пользователя, чем его (класса) содержимое |
Автор: EvilsInterrupt 23.4.2009, 17:25 | ||
Ну по сути, оно походит на вопрос любого программиста, которые разрабатывает либу для себя: "А как мне будет удобно ее юзать ?". Следовательно он пишет простенький пример кода использования, определяет интерфейс использования и тем самым приходит к "Интерфейс класса" |
Автор: Lazin 23.4.2009, 19:41 | ||||||
содержимое класса, пользователя волновать не должно, но только не разработчика класса ![]() архитектура приложения ведь не токлько из интерфейса состоит, к примеру
или
для программиста это не одно и то-же, но это один и тот-же дизайн, и в первом и во втором случае у нас есть некая сущность - поток данных, и мы в нее можем писАть и читать ![]() просто ОО дизайн позволяет сделать удобный интерфейс для того-же самого архитектурного решения, которое функционально эквивалентно, поэтому и нужно плясать не от того, как мы хотим что-бы это выглядело в коде, а от того, какую функциональность мы хотим получить ![]() |
Автор: bsa 23.4.2009, 23:27 |
Интерфейс класса вытекает из назначения. Реализация методов вытекает и из интерфейса, и из назначения, и из места, из которого у реализующего растут руки... Имхо. |
Автор: J0ker 24.4.2009, 20:34 | ||||
рад, что вы меня поняли ![]() |