Каковы различия между этими парадигмами программирования, и лучше ли они подходят для конкретных задач или предпочтения в каких-либо случаях использования одного над другими?
Примеры архитектуры приветствуются!
Каковы различия между этими парадигмами программирования, и лучше ли они подходят для конкретных задач или предпочтения в каких-либо случаях использования одного над другими?
Примеры архитектуры приветствуются!
Ответы:
Все они хороши по-своему - это просто разные подходы к одним и тем же проблемам.
В чисто процедурном стиле данные, как правило, сильно отделены от функций, которые над ним работают.
В объектно-ориентированном стиле данные обычно содержат набор функций.
В функциональном стиле данные и функции имеют тенденцию к тому, чтобы иметь больше общего друг с другом (как в Лиспе и Схеме), предлагая большую гибкость с точки зрения того, как функции фактически используются. Алгоритмы, как правило, также определяются с точки зрения рекурсии и композиции, а не циклов и итераций.
Конечно, сам язык влияет только на то, какой стиль предпочтительнее. Даже на чисто функциональном языке, таком как Haskell, вы можете писать в процедурном стиле (хотя это крайне нежелательно), и даже на процедурном языке, таком как C, вы можете программировать в объектно-ориентированном стиле (например, в GTK + и EFL API).
Чтобы было ясно, «преимущество» каждой парадигмы заключается просто в моделировании ваших алгоритмов и структур данных. Если, например, ваш алгоритм включает списки и деревья, функциональный алгоритм может быть наиболее разумным. Или, например, если ваши данные сильно структурированы, может иметь смысл составлять их как объекты, если это является нативной парадигмой вашего языка - или их можно так же легко написать как функциональную абстракцию монад, которая это родная парадигма языков, таких как Haskell или ML.
Выбор, который вы используете, - это просто то, что имеет больше смысла для вашего проекта и абстракций, поддерживаемых вашим языком.
Я думаю, что доступные библиотеки, инструменты, примеры и сообщества полностью превосходят эту парадигму в наши дни. Например, ML (или любой другой) может быть универсальным языком программирования общего назначения. но если вы не можете получить какие-либо хорошие библиотеки для того, что вы делаете, вы облажались.
Например, если вы создаете видеоигру, в C ++ есть больше хороших примеров кода и SDK, так что вам, вероятно, будет лучше. Для небольшого веб-приложения есть несколько отличных фреймворков Python, PHP и Ruby, которые помогут вам быстро начать работу. Java - отличный выбор для больших проектов из-за проверки во время компиляции и корпоративных библиотек и платформ.
Раньше случалось так, что стандартные библиотеки для разных языков были довольно маленькими и легко тиражировались - C, C ++, Assembler, ML, LISP и т. Д. Шли с основами, но имели тенденцию возиться, когда дело доходит до стандартизации вещей такие как сетевые коммуникации, шифрование, графика, форматы файлов данных (включая XML), даже базовые структуры данных, такие как сбалансированные деревья и хеш-таблицы, были опущены!
Современные языки, такие как Python, PHP, Ruby и Java, теперь поставляются с гораздо более приличной стандартной библиотекой и имеют много хороших сторонних библиотек, которые вы можете легко использовать, во многом благодаря тому, что они приняли пространства имен для предотвращения столкновения библиотек друг с другом, и сборка мусора для стандартизации схем управления памятью библиотек.
Эти парадигмы не должны быть взаимоисключающими. Если вы посмотрите на python, он поддерживает функции и классы, но в то же время все является объектом, включая функции. Вы можете смешивать и сочетать функциональный / oop / процедурный стиль в одном куске кода.
Я имею в виду, что в функциональных языках (по крайней мере, в Haskell, единственном, который я изучал) нет утверждений! функциям разрешено только одно выражение внутри них !! НО, функции являются первоклассными гражданами, вы можете передавать их как параметры вместе с кучей других способностей. Они могут делать мощные вещи с помощью нескольких строк кода.
В то время как на процедурном языке, таком как C, вы можете передавать функции только с помощью указателей на функции, и это само по себе не позволяет выполнять много мощных задач.
В python функция является гражданином первого класса, но она может содержать произвольное количество операторов. Таким образом, вы можете иметь функцию, которая содержит процедурный код, но вы можете передавать ее так же, как функциональные языки.
То же самое касается ООП. Такой язык, как Java, не позволяет вам писать процедуры / функции вне класса. Единственный способ передать функцию - обернуть ее в объект, реализующий эту функцию, а затем передать этот объект.
В Python у вас нет этого ограничения.
Для GUI я бы сказал, что объектно-ориентированная парадигма очень хорошо подходит. Окно - это объект, текстовые поля - это объекты, и кнопка «Окей» тоже одна. С другой стороны, такие вещи, как String Processing, могут быть выполнены с гораздо меньшими накладными расходами и, следовательно, более простыми с простой процедурной парадигмой.
Я не думаю, что это вопрос языка. Вы можете писать функциональные, процедурные или объектно-ориентированные практически на любом популярном языке, хотя в некоторых это может потребовать дополнительных усилий.
Чтобы ответить на ваш вопрос, нам нужны два элемента:
Список стилей / шаблонов архитектуры программного обеспечения показан в статье об архитектуре программного обеспечения. по на Википедии. И вы можете легко исследовать их в Интернете.
Короче говоря, Procedural хорош для модели, которая следует процедуре, ООП хорош для проектирования, а Functional хорош для программирования высокого уровня.
Я думаю, что вы должны попробовать прочитать историю каждой парадигмы и понять, почему люди ее создают, и вы можете легко их понять.
Поняв их обоих, вы можете связать элементы архитектурных стилей / шаблонов с парадигмами программирования.
Один из моих друзей пишет графическое приложение с использованием NVIDIA CUDA . Приложение очень хорошо вписывается в парадигму ООП, и проблему можно аккуратно разложить на модули. Однако для использования CUDA вам нужно использовать C, который не поддерживает наследование . Поэтому нужно быть умным.
а) Вы разрабатываете умную систему, которая в определенной степени будет эмулировать наследование. Это можно сделать!
я) Вы можете использовать систему крючков , которая ожидает, что у каждого дочернего элемента C родительского P будет определенное переопределение для функции F. Вы можете заставить детей регистрировать свои переопределения, которые будут сохраняться и вызываться при необходимости.
II) Вы можете использовать выравнивание структуры памяти функцию чтобы бросить детей в родителей.
Это может быть опрятным, но это не легко придумать надежное решение, ориентированное на будущее. Вы потратите много времени на разработку системы, и нет никаких гарантий, что вы не столкнетесь с проблемами в середине проекта. Реализация множественного наследования еще сложнее, если не почти невозможна.
б) Вы можете использовать согласованную политику именования и использовать подход « разделяй и властвуй» для создания программы. У него не будет никакого наследования, но поскольку ваши функции маленькие, простые для понимания и последовательно отформатированные, вам это не нужно. Количество кода, которое вам нужно написать, возрастает, очень сложно оставаться сосредоточенным и не поддаваться легким решениям (взломам). Однако этот способ кодирования ниндзя - это способ C-кодирования. Оставаться в равновесии между низкоуровневой свободой и написанием хорошего кода. Хороший способ добиться этого - написать прототипы на функциональном языке. Например, Haskell чрезвычайно хорош для прототипирования алгоритмов.
Я склоняюсь к подходу б. Я написал возможное решение, используя подход a, и, если честно, использование этого кода показалось мне неестественным.