Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Паттерны проектирования с примерами на UML диаграмме классов

Лекция



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

Паттерны проектирования с примерами на UML  диаграмме классов

Базовые паттерны

  • Mapper (Распределитель)
  • Money (Деньги)
  • Special Case (Особый Случай)
  • Plugin (Плагин)
  • Gateway (Шлюз)
  • Separated Interface (Выделенный интерфейс)
  • Registry (Реестр)
  • Service Stub (Сервисная заглушка)
  • Value Object (Объект-значение)
  • Record Set ()
  • Layer Supertype (Супертип Уровня)
  • Singleton (Одиночка)

Паттерны веб-представления

  • Transform View (Преобразователь)
  • Template View (Шаблонизатор)
  • Application Controller (Контроллер приложения)
  • Two Step View (Двухшаговая шаблонизация)
  • Page Controller (Контроллер страницы)
  • Front Controller (Контроллер входа / Единая точка входа)
  • MVC - Model View Controller (Модель-Вид-Контроллер)

Паттерны архитектуры источников данных

  • Row Data Gateway (Шлюз к данным записи)
  • Active Record (Активная запись)
  • Table Data Gateway (Шлюз к данным таблицы)
  • Data Mapper ()

Паттерны Объектно-Реляционной логики

  • Lazy Load (Ленивая загрузка)
  • Identity Map (Карта присутствия / Карта соответствия)
  • Unit of Work (Единица работы)

Паттерны Объектно-Реляционного структурирования

  • Identity Field (Поле первичного ключа)
  • Foreign Key Mapping (Разметка внешних ключей)
  • Association Table Mapping (Разметка таблиц связей)
  • Dependent Mapping (Управление распределением подчиненных сущностей)
  • Embedded Value (Объединенное свойство)
  • Serialized LOB (Сериализованный LOB)
  • Single Table Inheritance (Наследование с единой таблицей)
  • Class Table Inheritance (Наследование с таблицами классов)
  • Concrete Table Inheritance (Наследование с таблицами конечных классов)
  • Inherritance Mappers (Наследуемые распределители)

Паттерны логики сущности

  • Transaction Script (Сценнарий транзакции)
  • Domain Model (Модель области определения)
  • Table Module (Обработчик таблицы)
  • Service Layer (Сервисный уровень)

Паттерны обработки Объектно-Реляционных метаданных

  • Metadata Mapping (Распределение на основе метаданных)
  • Query Object (Объект-запрос)
  • Repository (Репозиторий)

Паттерны распределения данных

  • Remote Facade (Парадный вход)
  • Data Transfer Object (Объект передачи данных)

Паттерны локальной конкуренции

  • Optimistic Offline Lock (Оптимистичная блокировка)
  • Pessimistic Offline Lock (Пессимистичная блокировка)
  • Coarse Grained Lock (Грубая блокировка)
  • Implicit Lock (Скрытая блокировка)

Условные обозначения

Символ класса в UML диаграмме классов

Символ класса на диаграмме может выглядеть различным образом в зависимости от детализации диаграммы:
Паттерны проектирования с примерами на UML  диаграмме классов

Вопросы детализации будут рассмотрены в следующих разделах, а сейчас надо обратить внимание, что символ класса содержит имя (Player), набор операций (move, get_gealth) и атрибутов (pos, state). Для элементов класса могут задаваться тип, кратность, видимость и т.д.:

Формат спецификации атрибута:
видимость имя : тип [кратность] = значение_по_умолчанию

Формат спецификации операции:
видимость имя(аргумент: тип) = тип_возвращаемого_значения

В зависимости от параметра видимости элемент может быть:

  • приватным (private, доступен только внутри класса) — задается символом «минус» (-), может отображаться в виде квадрата;
  • защищенным (protected, доступен внутри класса, а также внутри классов-наследников) — задается символом «решетка» (#), может отображаться в виде ромба;
  • открытым (public, доступен всем) — задается символом «плюс» (+), может отображаться в виде круга.

Виртуальная функция и имя абстрактного класса выделяются курсивом, а статическая функция — подчеркивается.

Виды паттернов банды четырех

  • Паттерны проектирования с примерами на UML  диаграмме классов — поведенческие (behavioral);
  • Паттерны проектирования с примерами на UML  диаграмме классов — порождающие (creational);
  • Паттерны проектирования с примерами на UML  диаграмме классов — структурные (structural).

  • Паттерны проектирования с примерами на UML  диаграмме классов

1.2 Отношения классов на UMLдиаграмме

Условные обозначения отношения между классами

  • Паттерны проектирования с примерами на UML  диаграмме классов — агрегация (aggregation) — описывает связь «часть»–«целое», в котором «часть» может существовать отдельно от «целого». Ромб указывается со стороны «целого».
  • Паттерны проектирования с примерами на UML  диаграмме классов — композиция (composition) — подвид агрегации, в которой «части» не могут существовать отдельно от «целого».
  • Паттерны проектирования с примерами на UML  диаграмме классов — зависимость (dependency) — изменение в одной сущности (независимой) может влиять на состояние или поведение другой сущности (зависимой). Со стороны стрелки указывается независимая сущность.
  • Паттерны проектирования с примерами на UML  диаграмме классов — обобщение (generalization) — отношение наследования или реализации интерфейса. Со стороны стрелки находится суперкласс или интерфейс.

диаграмма классов допускает различные виды отношений, рассмотрим их на части диаграммы модели некоторой игры:
Паттерны проектирования с примерами на UML  диаграмме классов

В игре есть различные виды элементов (стены, сундуки, персонажи). Все эти элементы являются наследниками абстрактного класса AbstractItem, при этом часть из них умеет двигаться (такие элементы должны быть унаследованы от MovingItem). Наследование (отношение «является») изображается с помощью сплошной линии с закрытой стрелки, направленной в сторону суперкласса — на диаграмме класс MovingItem унаследован от AbstractItem, класс Player — от MovingItem и т.д. Штриховая линия с закрытой стрелкой задает отношение реализации (закрытое наследование).

Другой вид отношений между классами — включение, в объектно-ориентированном программировании различают два вида этого отношения — композицию и агрегацию. Об этом говорит сайт https://intellect.icu . Напомню, что композиция — это разновидность включения, когда объекты неразрывно связаны друг с другом (время их жизни совпадает), в случае агрегации, время жизни различно (например, когда объект вложенного класса может быть заменен другим объектом во время выполнения программы).

Отношение композиции обозначается закрашенным ромбом, который рисуется со стороны включающего класса — так, класс MovingItem включает в себя класс Position, т.к. перемещающийся объект всегда имеет позицию. Отношение агрегации изображается незакрашенным ромбом — игрок (Player) агрегирует состояние (IPlayerState).

Если вы знакомы с паттернами State, Strategy или Delegation — секцию можно пропустить.
На приведенной выше диаграмме используется шаблон проектирования Состояние (State), являющийся разновидностью шаблона Делегирование (Delegation) и близкой к паттерну Стратегия (Strategy). Суть делегирования заключается в том, что для упрощения логики работы класса, часть его работы может быть передана (делегирована) вспомогательному классу. В свою очередь, паттерн State может быть добавлен, например, на этапе рефакторинга если в нескольких функциях класса встречается разлапистая проверка состояния объекта для выполнения тех или иных действий. В нашем случае персонаж может взаимодействовать с ежом, предположим, что если персонаж движется сидя и контактирует с ежом — у него должно уменьшится здоровье, а если стоя — увеличится счет (points). Кроме ежа могла быть еда, противники, патроны и т.д. Для демонстрации такого паттерна создан абстрактный класс IPlayerState и два наследника StayState и SeatState. В классе Player, при нажатии кнопки Ctrlсостояние могло бы меняться на SeatState, а при отпускании — на StayState. Таким образом, при выполнении state->process_hedgehog(this)наш игрок каким-то образом, определенным объектом state, проконтактирует с ежиком.

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

Наиболее общий вид отношений между классами — ассоциация, обозначается сплошной линией (иногда со стрелкой). Вообще, и композиция, и агрегация, и обобщение (наследование) — являются частными случаями ассоциации. В нашей диаграмме с помощью ассоциации показано, что класс IPlayerState изменяет stats (health и points) объекта Player. Ассоциация может иметь название связи, поясняющую суть отношения. В качестве названия связей композиции и агрегации часто используется имя соответствующей переменной. Кроме того, ассоциация может иметь кратность, она задается на концах линии:

  • 1 — одна связь (на нашей диаграмме показано, что один игрок включает в себя один экземпляр класса IPlayerState);
  • * любое число связей (если бы на диаграмме был класс игрового поля, то с помощью звездочки можно было бы показать, что оно может содержать произвольное число игровых элементов);
  • [от..до] — может задаваться диапазоном. Так диапазон [0..*] эквивалентен звездочке, но если мы захотим показать, что должно присутствовать более одного объекта — можем записать [1..*]

Последний вид отношений, который мы рассмотрим — зависимость, изображается штриховой (прерывистой) линией. Если есть стрелка — то направлена от зависимого к независимому классу, если стрелки нет — то классы зависят друг от друга. Под зависимостью понимается зависимость от интерфейса, т.е. если интерфейс независимого класса изменится — то придется вносить изменения в зависимый класс. В нашей диаграмме SeatState и StayState зависят от класса Player, т.к. обращаются к его методам для изменения характеристик игрока. Для изображения отношения дружбы между классами используется отношение зависимости с подписью friend.

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

Список шаблонов (паттернов) проектирования с использованием UML диаграммы классов

Паттерны проектирования с примерами на UML  диаграмме классов

Хранитель (memento)

Паттерны проектирования с примерами на UML  диаграмме классов

Цепочка обязанностей (chain of responsibility)

Паттерны проектирования с примерами на UML  диаграмме классов

Наблюдатель (observer)

Паттерны проектирования с примерами на UML  диаграмме классов

Команда (command)

Паттерны проектирования с примерами на UML  диаграмме классов

Состояние (state)

Паттерны проектирования с примерами на UML  диаграмме классов

Интерпретатор (interpreter)

Паттерны проектирования с примерами на UML  диаграмме классов

Стратегия (strategy)

Паттерны проектирования с примерами на UML  диаграмме классов

Итератор (iterator)

Паттерны проектирования с примерами на UML  диаграмме классов

Шаблонный метод (template method)

Паттерны проектирования с примерами на UML  диаграмме классов

Посредник (mediator)

Паттерны проектирования с примерами на UML  диаграмме классов

Посетитель (visitor)

Паттерны проектирования с примерами на UML  диаграмме классов

Адаптер (adapter)

Паттерны проектирования с примерами на UML  диаграмме классов

Прокси (proxy)

Паттерны проектирования с примерами на UML  диаграмме классов

Мост (bridge)

Паттерны проектирования с примерами на UML  диаграмме классов

Абстрактная фабрика (abstract factory)

Паттерны проектирования с примерами на UML  диаграмме классов

Компоновщик (composite)

Паттерны проектирования с примерами на UML  диаграмме классов

Строитель (builder)

Паттерны проектирования с примерами на UML  диаграмме классов

Декоратор (decorator)

Паттерны проектирования с примерами на UML  диаграмме классов

Фабричный метод (factory method)

Паттерны проектирования с примерами на UML  диаграмме классов

Фасад (facade)

Паттерны проектирования с примерами на UML  диаграмме классов

Прототип (prototype)

Паттерны проектирования с примерами на UML  диаграмме классов

Приспособленец (flyweight)

Паттерны проектирования с примерами на UML  диаграмме классов

Одиночка (singleton)

Паттерны проектирования с примерами на UML  диаграмме классов

2 Использование диаграммы классов

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

Стоит отметить, что у Гради Буча советы по использованию UML даны в книге «Руководство пользователя» [Buch_Rambo], но в его «Объектно-ориементированном анализе» [Buch] можно найти хорошие примеры и критерии качества проекта. Леоненков [Leonenkov] и вовсе избегает этой темы, оставляя лишь ссылки на литературу, конкретные рекомендации я нашел у Лармана [Larman] и Розенберга [Rosenberg], часть материала основана на моем личном опыте. Фаулер рассматривает UML как средство эскизирования, поэтому у него свой (сильно отличающийся от Буча и Розенберга) взгляд на диаграмму классов [Fauler].

2.1 Диаграмма классов как словарь системы, концептуальная модель

Словарь системы формируется параллельно с разработкой диаграммы прецедентов, т.е. технического задания. Выглядит это следующим образом — вы задаете заказчику вопросы типа «что еще может сделать пользователь?», «что произойдет (должна выдать система) если пользователь сделает нажмет на <эту> кнопку?», а ответы на них записываете в виде описания прецедентов. Однако, заказчик, давая ответы может называть одни и те же вещи разными именами — из личного опыта: говоря «клетка», «пересечение», «узел» и «ячейка» заказчик может иметь ввиду одно и тоже. В вашей же системе все эти понятия должны быть представлены одной абстракцией (классом/функцией/…). Для этого при общении с заказчиком стоит фиксировать терминологию в виде словаря системы — очень хорошо с этим справляется диаграмма классов.

Гради Буч для построения словаря системы предлагает выполнять в следующем порядке [BuchRambo]:

  1. анализируя прецеденты, определить какие элементы пользователи и разработчики применяют для описания задачи или ее решения;
  2. выявить для каждой абстракции соответствующее ей множество обязанностей (ответственности). Проследите правильность распределения обязанностей (в том числе, соблюдение принципа единой обязанности [solid_refactoring]);
  3. разработайте процедуры и операции для выполнения классами своих обязанностей.

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

Паттерны проектирования с примерами на UML  диаграмме классов

В процессе проектирования словарь системы может дополняться, Розенберг очень хорошо демонстрирует это в своей книге описывая итеративный процесс проектирования ICONIX [Rosenberg]. Например, после рассмотрения нескольких прецедентов может оказаться, что несколько классов реализуют один и тот же функционал — для решения проблемы надо более четко прописать обязанности каждого класса, возможно, добавить новый класс и перенести часть этих обязанностей ему.

Ларман предлагает строить концептуальную модель системы [Larman] — это примерно то, что мы описали как словарь системы, но помимо терминов предметной области в ней фиксируются некоторые отношения, понятные заказчику. Например, заказчик понимает (и фиксирует в техническом задании), что <покупку> оформляет <продавец> — следовательно, между продавцом и покупкой существует отношение ассоциации "оформляет". Я рекомендую строить концептуальную модель, дорабатывая словарь системы, хотя Ларман рекомендует сначала добавлять ассоциации, а затем — атрибуты.

2.2 Диаграмма классов уровня проектирования

В любом объектно-ориентированном процессе проектирования диаграмма классов является результатом, т.к. является моделью, наиболее близкой к реализации (коду). Существуют инструменты, способные преобразовать диаграмму классов в код — такой процесс называется кодогенерацией и поддерживается множеством IDE и средств проектирования. Например, кодогенерацию выполняет Visual Paradigm (доступно в виде плагинов для множества IDE), новые версии Microsoft Visual Studio, такие средств UML-моделирования как StarUML, ArgoUML и др. Чтобы построить по диаграмме хороший код, она должна быть достаточно подробной. Именно о такой диаграмме идет речь в этом разделе.

До Ларману [Larman] до начала построения диаграммы классов уровня проектирования должны быть построены диаграммы взаимодействия и концептуальная модель системы. При этом порядок построения диаграммы следующий:

  1. перенести классы с диаграммы последовательности;
  2. добавить атрибуты концептуальной модели;
  3. добавить имена методов по анализу диаграмм взаимодействия (например, диаграмм последовательностей [uml_sequence_diag]);
  4. добавить типы атрибутов и методов;
  5. добавить ассоциации (на основании атрибутов — отношения композиции и агрегации);
  6. добавить стрелки (направление ассоциаций)
  7. добавить ассоциации, определяющие другие виды отношений (в первую очередь, наследование).

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

Например, при анализе задания на игру «Сапер» мы выделили классы <Флажок> и <Мина>, но будут ли эти классы в окончательном проекте или останутся только в воображении? — решение можно принять только проанализировав диаграммы взаимодействия. Ведь возможен и такой код:

  1. enum class CellType {
  2. EmptyOpened, EmptyClose, EmptyCloseFlagged,
  3. MineOpened, MineClose, MineCloseFlagged
  4. };
  5. class PlayingGround {
  6. // ...
  7. CellType **m_ground;
  8. }

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

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

2.3 Диаграмма классов для эскизирования, документирования

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

Сторонником применения UML для эскизирования является Фаулер [Fauler], который считает, что целостный процесс проектирования с использованием UML слишком сложен. Эскизирование применяется очень часто (не только при объяснении проекта на маркерной доске):

  • в любой книге, посвященной паттернам проектирования, вы найдете массу UML диаграмм, выполненных в этом стиле;
  • при моделировании прецедента выбираются классы, за счет которых этот прецедент реализуется. Моделирование прецедента выполняется при рефакторинге;
  • в документацию для разработчиков нет смысла вставлять диаграмму классов уровня проектирования — гораздо полезнее описать наиболее важные (ключевые) моменты системы. Для этого строятся эскизные диаграммы классов и диаграммы взаимодействия. Также существуют специальные инструменты построения документацию по готовому коду — такие как JavaDoc или Doxygen[doxygen_codegeneration], в частности они строят диаграмму классов, но чтобы документация была понятной, в исходный код программы требуется вносить комментарии специального вида.

Каких-либо конкретных рекомендаций к эскизам диаграмм классов предложить невозможно, кроме того, обычно это достаточно простая задача. Важно понимать суть — избирательность представления элементов снижает сложность восприятия диаграммы.

3.4 Диаграмма классов для моделирования БД

Частным случаем диаграммы классов является диаграмма «сущность-связь» (E-R диаграмма), используемая для моделирования логической схемы базы данных. В отличии от классических E-R диаграмм, диаграмма классов позволяет моделировать поведение (триггеры и хранимые процедуры).

Обычно ситуация выглядит следующим образом — вы разработали систему, состояние которой нужно сохранять между запусками, например:

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

Хранимые между запусками данные должны каким-то образом загружаться по запросу пользователя, т.е. должны задаваться параметры соответствующих классов. Например, приложение должно получить из базы данных список треков (маршрутов) и отобразить его в виде списка в меню программы. При выборе элемента списка — запросить в БД параметры трека, создать объект трека и отобразить его на карте. В любом случае, данные с базы используются при инициализации объектов программы — это важно понимать.

Для моделирования схемы БД с помощью диаграммы классов нужно [Buch_Rambo]:

  1. идентифицировать классы, данные которых должны храниться между запусками приложения (или обращениями пользователя) и нанести эти классы на отдельную диаграмму;
  2. детально специфицировать атрибуты классов, ассоциации и кратности. В E-R модели кратности имеют огромное значение — так например, при наличии кратности «многие-ко-многим» придется создавать вспомогательную таблицу. Используйте специфические стереотипы классов и пометки атрибутов (для задания первичных и вторичных ключей, например) [uml_datamodeling];
  3. решить проблемы использования полученной диаграммы в качестве физической модели базы данных — циклические ассоциации, n-арные ассоциации и т.д. При необходимости создать промежуточные абстракции;
  4. раскрыть операции, важные для доступа к данным и поддержания целостности;

Вау!! 😲 Ты еще не читал? Это зря!

паттерны проектирования классов и объектов

Механизмы повторного использования

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

Ответы на вопросы для самопроверки пишите в комментариях, мы проверим, или же задавайте свой вопрос по данной теме.

создано: 2017-07-31
обновлено: 2024-11-14
86



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Проектирование веб сайта или программного обеспечения

Термины: Проектирование веб сайта или программного обеспечения