Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения


НазваниеКонспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения
страница6/10
ТипКонспект
1   2   3   4   5   6   7   8   9   10

3.2 Подходы к проектированию программ в целом
ООП ориентировано на разработку крупных программных комплексов, разрабатываемых командой программистов (возможно, достаточно большой). Проектирование системы в целом, создание отдельных компонентов и их объединение в конечный продукт при этом часто выполняется разными людьми, и нет ни одного специалиста, который знал бы о проекте всё.

Объектно-ориентированное проектирование состоит в описании структуры и поведения проектируемой системы, то есть, фактически, в ответе на два основных вопроса:

  • из каких частей состоит система;

  • в чём состоит ответственность каждой из частей.

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

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

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

Родственные методологии

Компонентное программирование – следующий этап развития ООП; прототип- и класс-ориентированное программирование – разные подходы к созданию программы, которые могут комбинироваться, имеющие свои преимущества и недостатки.
Компонентное программирование

Компонентно-ориентированное программирование – это своеобразная «надстройка» над ООП, набор правил и ограничений, направленных на построение крупных развивающихся программных систем с большим временем жизни. Программная система в этой методологии представляет собой набор компонентов с хорошо определёнными интерфейсами. Изменения в существующую систему вносятся путём создания новых компонентов в дополнение или в качестве замены ранее существующих. При создании новых компонентов на основе ранее созданных запрещено использование наследования реализации – новый компонент может наследовать лишь интерфейсы базового. Таким образом компонентное программирование обходит проблему хрупкости базового класса.
Прототипное программирование

Прототипное программирование, сохранив часть черт ООП, отказалось от базовых понятий – класса и наследования.

  • Вместо механизма описания классов и порождения экземпляров язык предоставляет механизм создания объекта (путём задания набора полей и методов, которые объект должен иметь) и механизм клонирования объектов.

  • Каждый вновь созданный объект является «экземпляром без класса». Каждый объект может стать прототипом – быть использован для создания нового объекта с помощью операции клонирования. После клонирования новый объект может быть изменён, в частности, дополнен новыми полями и методами.

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


Класс-ориентированное программирование

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

Гради Буч указывает на следующие причины, приводящие к снижению производительности программ из-за использования объектно-ориентированных средств:

Динамическое связывание методов.

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

Значительная глубина абстракции.

ООП-разработка часто приводит к созданию «многослойных» приложений, где выполнение объектом требуемого действия сводится к множеству обращений к объектам более низкого уровня. В таком приложении происходит очень много вызовов методов и возвратов из методов, что, естественно, сказывается на производительности.

Наследование «размывает» код.

Код, относящийся к «конечным» классам иерархии наследования, которые обычно и используются программой непосредственно, находится не только в самих этих классах, но и в их классах-предках. Относящиеся к одному классу методы фактически описываются в разных классах. Это приводит к двум неприятным моментам:

  • Снижается скорость трансляции, так как компоновщику приходится подгружать описания всех классов иерархии.

  • Снижается производительность программы в системе со страничной памятью – поскольку методы одного класса физически находятся в разных местах кода, далеко друг от друга, при работе фрагментов программы, активно обращающихся к унаследованным методам, система вынуждена производить частые переключения страниц.

Инкапсуляция снижает скорость доступа к данным.

Запрет на прямой доступ к полям класса извне приводит к необходимости создания и использования методов доступа. И написание, и компиляция, и исполнение методов доступа сопряжены с дополнительными расходами.

Динамическое создание и уничтожение объектов.

Динамически создаваемые объекты, как правило, размещаются в куче, что менее эффективно, чем размещение их на стеке и, тем более, статическое выделение памяти под них на этапе компиляции.

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

В методологии ХР имеется много спорных моментов. Одним Из ключевых таких моментов является то, что она базируется на Эволюционном, а не предварительном проектировании. А как мы уже выяснили, использование эволюционного проектирования не может привести ни к чему хорошему из-за обилия сию минутных проектировочных решений и энтропии программного продукта.

В основе этого утверждения лежит кривая стоимости изменений в программном продукте. Согласно этой кривой по мере раз вития проекта стоимость внесений изменений экспоненциально возрастает. Получается, что если экспоненциальная кривая вер на, то эволюционное проектирование вообще нельзя использовать в работе. Отсюда же следует, что нельзя делать ошибки в предварительном проектировании – затраты на их исправление будут определяться все той же зависимостью.

В основе ХР лежит предположение, что эту кривую можно сгладить до такой степени, чтобы можно было применять эволюционное проектирование. Такое сглаживание, с одной стороны, возникает при использовании методологии ХР, а с другой — оно же в ней и используется. Это еще раз подчеркивает тесную взаимосвязь между практиками ХР: нельзя использовать те части методологии, которые предполагают существование сглаживания, не используя те практики, которые это сглаживание осуществляют.

У практик, с помощью которых осуществляется сглаживание, есть множество составляющих. В основе всех их лежит Тестирование и непрерывная интеграция. Именно надежность кода, которую обеспечивает тестирование, делает возможным все остальное в этой методологии. Непрерывная интеграция не обходима для синхронной работы всех разработчиков, так чтобы любой человек мог вносить в систему свои изменения и не бес покоиться об интеграции с остальными членами команды. Взятые вместе, эти две практики могут оказывать существенное влияние на кривую стоимости изменений в программном продукте.

Подобный эффект имеет и рефакторинг (переработка написанного кода). Те, кто делают рефакторинг в той строгий манере, что принята в ХР, отмечают значительное повышение его эффективности по сравнению с более бессистемной реструктуризацией.

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

В ХР очень популярны два лозунга: «Do the Simplest Thing that Could Possibly Work» («Ищите самое простое решение, кото рое может сработать») и YAGNI («You Aren't Going to Need It» — «Это вам не понадобится»)- Оба они олицетворяют собой одну из практик ХР под названием Простой дизайн.

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

Тем не менее ХР не советует заниматься созданием гибких компонентов и каркасов до того, как понадобится именно эта функциональность. Лучше, если эти структуры будут наращиваться по мере необходимости. Если сегодня мне нужен класс Money, который обрабатывает сложение, а не умножение, то сегодня я буду встраивать в этот класс только сложение. Даже если я абсолютно уверен, что умножение понадобится мне уже в следующей итерации, и я знаю, как очень просто и быстро это сделать сейчас, все равно я должен оставить это на следующую итерацию, когда в нем появится реальная необходимость.

Такое поведение оправдано с экономической точки зрения. Занимаясь работой, которая понадобится только завтра, я тем самым расходую силы и время, предназначенные для задач, которые должны были быть сделаны сегодня. План выпуска про граммы четко указывает, над чем мне нужно работать в настоящий момент. Если я отклоняюсь от него, чтобы поработать над тем, что понадобится в будущем, я нарушаю свое соглашение с заказчиком. Кроме того, появляется риск не успеть сделать все записанное в требованиях для текущей итерации. И даже в том случае, если такой опасности нет и у вас появилось свободное время, то решать, чем вам заняться. — прерогатива заказчика, который может попросить заняться вовсе не умножением.

Таким образом, возможные препятствия экономического характера осложняются еще и тем, что мм можем ошибаться. Даже если мы абсолютно уверены в том, как работает эта функция, мы все равно можем ошибиться, особенно если у нас еще нет подробных требований заказчика. А чем раньше мы используем в работе над проектом ошибочные решения, тем хуже. Приверженцы методологии ХР считают, что в такой ситуации гораздо легче принять неправильное решение.

Другая причина, по которой простой дизайн лучше сложно го, — отказ от принципа «блуждающего огонька». Сложную конструкцию гораздо труднее понять, чем простую. Именно поэтому любая модификация системы делает ее все более сложной. Это опять-таки ведет к увеличению стоимости работ в период между тем временем, когда дизайн системы стал более сложным, и временем, когда это действительно стало необходимо [3].

Такой стиль работы многим кажется абсурдным, и надо сказать, что они правы. Правы при одном условии — абсурд получится, если эту практику начать применять в обычном процессе разработки, а все остальные практики ХР игнорировать. Если же изменить существующий баланс между эволюционным и предварительным проектированием, то YAGNI становится очень полезным принципом (тогда и только тогда).

Подведем итог. Не стой; расходовать силы на то, чтобы внести в систему новую функциональность, если она не понадобится до следующей итерации. Даже если это практически ничего не стоит, вам не нужно это делать, так как это увеличит общую стоимость модификации. Однако для того, чтобы осознанно применять такой принцип на деле, вам нужно использовать ХР или другую подобную методологию, которая снижает стоимость изменений.
Простой дизайн

Итак, необходимо, чтобы программный код был максимально прост. В конце концов, кому нужно, чтобы код был сложный и запутанный? Осталось только понять, что мы разумеем под словом «простой».

В книге Extreme Programming Explained Кент приводит четыре критерия простой системы. Вот они в порядке убывания важности:

  • система успешно проходит все тесты;

  • код системы ясно раскрывает все изначальные замыслы;

  • в ней отсутствует дублирование кода;

  • используется минимально возможное количество классов и методов.

Успешное тестирование системы — довольно простой критерий. Отсутствие дублирования кода тоже вполне четкое требование, хотя большинство разработчиков нужно учить, как этого достичь. Самое сложное скрывается в слонах «раскрывает изначальные замыслы». Что это значит?

Основное достоинство программного кода в данном случае — его ясность. ХР всячески подчеркивает, что хороший код — это код, который можно легко прочесть. Скажите ХР-шнику, что он пишет «заумный код», и будьте уверены, что обругали этого человека. Но понимание замыслов программиста, написавшего код, зависит также и от опыта и ума того, кто этот код пытается прочесть. Однако отмстим, что не стоит думать над вопросом, как сделать дизайн максимально простым. В конце концов, позже вы сможете (и должны, и будете) заняться рефакторингом. В конце работы над проектом желание делать рефакторинг гораздо важнее, чем точное понимание того, какое решение является самым простым.

Эта тема сравнительно недавно всплыла в списке рассылки, посвященном ХР, и, коль скоро мы заговорили о роли проектирования, нам стоит ее обсудить.

Дело в том, что процесс рефакторинга требует времени, но не добавляет новой функциональности. С другой стороны, принцип YAGN1 гласит, что надо проектировать только для те кущей функциональности, а не для того, что понадобится в будущем. Не сталкиваемся ли мы здесь с противоречием?

Принцип YAGNI состоит в том, чтобы не делать систему более сложной, чем того требует реализация текущих задач. Это является частью практики «Простой дизайн». Рефакторинг же необходим для поддержания системы в максимально простом состоянии. Его нужно проводить сразу же, как только вы обнаружите, что можете что-либо упростить.

Простой дизайн одновременно задействует практики ХР и сам по себе является основополагающей практикой. Только при условии тестирования, непрерывной интеграции и рефакторинга можно говорить об эффективном использовании простого дизайна. Но в то же время простой дизайн абсолютно необходим для сглаживания кривой стоимости изменений. Любая излишне сложная конструкция затруднит внесение изменений в систему по всем направлениям, за исключением того из них, ради которого эта сложность в нее вносилась. Однако редко удается пред сказать такое направление, поэтому лучше будет стремиться к простым решениям. И в то же время мало кому удается сделать все максимально просто с первого раза, так что вам придется заниматься рефакторингом, чтобы приблизиться к цели.
Наращивание архитектуры

Термин «архитектура» передает идею основных элементов системы, тех ее частей, которые трудно изменить. Они являются фундаментом, на котором можно построить все остальное.

Какую роль играет архитектура в эволюционном проектировании? Критики ХР считают, что эта методология вообще не признает работы над архитектурой, что вся суть ХР — сразу садиться за написание кода и уповать на то, что рефакторинг решит все проблемы с проектированием. Они правы, и, может быть, в этом заключается некоторая слабость ХР Приверженцы ХР - Кент Бек (Kent Beck), Рон Джеффриз (Ron Jeffries) и Боб Мартин (Bob Martin) — прикладывают очень много сил, чтобы вообще избежать любого предварительного проектирования архитектуры. Не добавляйте в систему базу данных, пока она вам действительно не понадобилась. Работайте поначалу с файлами, а база данных появится в следующей итерации, в результате ре-факторинга.

Однако рекомендуется все-таки начинать работу с приблизительной опенки архитектуры системы. Если вы видите большое количество данных и множество различных пользователей, смело включайте в архитектуру базу данных. Если вы должны работать со сложной бизнес-логикой, используйте модель предметной области. Однако не забывайте об уважении к богам YAGNI и в сомнительных случаях отдавайте предпочтение более простым решениям. Кроме того, всегда будьте готовы вы бросить кусок архитектуры, если видите, что он не приносит
UML и ХР

В идеале ХР полностью отрицает проектирование системы, в частности методами UML. Тем не менее программисты все же часто используют на начальном этапе диаграммы UML. На самом деле диаграммы очень полезны для понимая разрабатываемого продукта, но чтобы они сделали процесс более длительным и трудоемким, необходимо их использовать правильно.

Советы тем, кто хочет правильно использовать диаграммы.

Во-первых, пока рисуете диаграмму, не забывайте, для чего вы это делаете. Основное ее достоинство — коммуникация с людьми. Чтобы коммуникация была эффективной, нужно отображать на диаграмме только важные аспекты, не обращая внимания на все второстепенные. Такая избирательность — основа правильной работы с UML. Не надо отображать на диаграмме каждый класс —- только самые важные. У классов не нужно задавать каждый атрибут или операцию — только самые важные. Не надо рисовать диаграммы последовательности для всех вариантов использования и сценариев — ну, и так далее. Самая распространенная проблема с использованием диаграмм — это то, что их пытаются сделать максимально всеобъемлющими. Однако самый лучший источник всеобъемлющей информации — это программный код, так как именно его легче всего синхронизировать с кодом. Для диаграммы же всеобъемлемость – враг удобопонятности.

Чаще всего диаграммы используются для того, чтобы про анализировать проектные решения еще до написания кода. Не редко при этом возникает чувство, что в ХР этого делать нельзя. Это совсем не так. Многие полагают, что перед разработкой сложной задачи стоит ненадолго собраться всей командой для ее предварительного проектирования. Тем не менее, когда проводите такие собрания, не забывайте, что:

  • они должны быть действительно недолгими;

  • не нужно обсуждать все подробности (только самое важное);

  • относитесь к полученному в результате проектному решению как к наброску, а не как к конечной версии, не подверженной изменениям.

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

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

Кроме того, UML-диаграммы используются в качестве документации по проекту. Как правило, в своей обычной форме это модель, редактируемая с помощью некоторого CASE-инструмента. Идея здесь состоит в том, что ведение такой документации облегчает работу. На самом деле, чаще всего она вообще не нужна, поскольку:

  • нужно постоянно тратить массу времени, чтобы не дать диаграммам устареть, в противном случае они не будут со ответствовать программному коду;

  • диаграммы находятся внутри сложного CASE-средства либо в толстенной папке, и никто туда не заглядывает.

Итак, если вы хотите иметь текущую документацию по проекту, учитывайте все вышеперечисленные проблемы:

  • используйте только те диаграммы, которые вы можете поддерживать без особых усилий;

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

  • посмотрите, обращают ли ваши разработчики на диаграммы хоть какое-то внимание, и если нет, выбросите их.

И наконец, последний аспект использования UML для документации — передача проекта в другие руки (например, от од ной группы разработчиков другой). Согласно методологии ХР создание документации — такая же задача, как и все остальные, а значит, ее приоритет должен быть определен заказчиком. В этой ситуации может пригодиться UML, разумеется, при условии избирательности диаграмм, которые создавались с целью облегчения коммуникации. Помните, что программный код — это основной репозиторий подробной информации, а диаграммы служат для обобщенного представления основных аспектов системы.
Суть проектирования. Программирование и тестирование

Проектирование в ХР требует от человека следующих качеств:

  • постоянного желания сохранять программный код простым и понятным насколько это возможно;

  • наличия навыков рефакторинга, так чтобы с уверенностью вносить в систему изменения, как только в этом возникнет необходимость;

  • хорошего знания паттернов: рассматривать их не просто как готовые решения, а оценивать своевременность и использовать постепенно, от простого к сложному;

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

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

По результатам этой встречи программисты составляют спи сок тестовых примеров, которые необходимо прогнать до завершения реализации задачи. Из списка выбирается такой тест, в реализации которого программисты полностью уверены и с по мощью которого они смогут лучше понять суть задачи. Пишется тестовая программа. Если она сразу нормально заработает, можно двигаться дальше. Однако, как правило, без проблем не обходится. В случае если тест не работает, возможна одна из следующих ситуаций:

  • мы знаем простой способ заставить его работать, и мы действуем этим способом;

  • мы знаем сложный и очень неприятный способ заставить его работать, но понимаем, как изменить архитектуру системы и добиться нормальной работы тестового примера без лишних усилий. Тогда мы решаемся на переработку системы;

  • мы знаем сложный и неприятный способ заставить его работать и не видим никакой возможности переработать систему, поэтому мы идем этим сложным путем.

После того как тест заработал, мы, возможно, снова поймем, как усовершенствовать систему, что и сделаем.

Вполне вероятно, что в ходе реализации тестового примера мы найдем другой тестовый пример, который также должен работать. Мы заносим новый тест в свой список и продолжаем разработку. Возможно, мы обнаружим, что масштабы перестройки системы. выходят за рамки требований текущего теста, тогда зафиксируем и этот факт и двинемся дальше. В конце концов, наша цель — сконцентрироваться на деталях и успешно справиться С конкретной проблемой, но одновременно не потерять общего представления о системе, которое формируется в процессе интенсивной работы над кодами.
1   2   3   4   5   6   7   8   9   10

Похожие:

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций междисциплинарного курса мдк. 03. 04. Web-программирование
Наконец, последняя выделяемая нами архитектура предназначена для построения глобальных распределенных информационных приложений с...

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconОпорный конспект лекций по мдк 05. 01 Технология работ по профессии Кассир
ПМ. 05 Выполнение работ по одной или нескольким профессиям рабочих, должностям служащих

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций содержание право социального обеспечения часть 5...
Перечень документов подтверждающих условие присвоения звания – ветеран труда, утверждено постановлением правительства №11 – пп от...

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций удк 651. 5 Ббк 60. 844 Конспект лекций по курсу «Делопроизводство»
Конспект лекций по курсу «Делопроизводство» составлен на основе базовой программы «Делопроизводство и документационное обеспечение...

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций для студентов I курса медицинского факультета специальности «Стоматология»
Химия. Конспект лекций для студентов I курса медицинского факультета специальности «Стоматология». Часть Общая химия. М.: Изд-во...

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций для студентов всех форм обучения специальности 080110...
Налоги и налогообложение: Конспект лекций / Составитель Н. А. Леончик. – Кемерово, 2006. – 80 с

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций мдк 01. 01. Организация безналичных расчетов для...
Пм 01. «Ведение расчетных операций», рассмотренной пцк от 31 августа 2016 г протокол №1

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций Владимир 2010 Министерство образования Российской...
Автоматизированные системы бухгалтерского и управленческого учета. Часть 1: Конспект лекций / Владим гос ун-т; Сост.: Д. Н. Васильев...

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconКонспект лекций мдк 01. 01. Организация расчетов по счетам Федерального...
Пм 01. «Ведение расчетных операций», рассмотренной пцк от 31 августа 2016 г протокол №1

Конспект лекций междисциплинарного курса мдк. 03. 01 Технология разработки программного обеспечения iconВопросы к экзамену по мдк 02. 01. «Технология и организация сопровождения туристов»
Вопросы к экзамену по мдк 02. 01. «Технология и организация сопровождения туристов» для студентов 2 курса специальности «Туризм»

Вы можете разместить ссылку на наш сайт:


Все бланки и формы на filling-form.ru




При копировании материала укажите ссылку © 2019
контакты
filling-form.ru

Поиск