编程范式
思维导图
一.编程语言
1.机器语言
机器语言是计算机可以直接理解和执行的语言,是计算机硬件可以处理的二进制代码。它是一种低级语言,用于编写计算机程序并控制计算机硬件。机器语言常常由一系列二进制指令组成,用于执行计算机硬件的基本操作,例如加载、存储、移位、加减乘除等操作。 机器语言的使用通常需要编写相当底层的代码,比如汇编语言,而且编写过程相对繁琐复杂,需要对计算机的硬件结构和算法有深刻的理解。因此,使用高级语言编写程序要比使用机器语言更容易和高效。现代计算机通常使用二进制指令集与汇编语言或SAS(符号地址汇编语言)交互,而高级语言编写的程序在编译后就被转换为计算机可以理解的机器语言。 尽管机器语言编程复杂和困难,但机器语言在编写低级别的系统程序以及编写受限的硬件程序时仍然非常重要。同时,机器语言由于执行效率高,仍然被用于编写一些特定领域的计算机软件。
2.汇编语言
汇编语言是介于机器语言和高级语言之间的一种低级语言,用于编写计算机程序并控制计算机硬件。汇编语言是一种符号性的语言,通过将符号操作码或指令助记符(mnemonics)映射到机器指令(二进制代码)来完成编译。相比机器语言,汇编语言更加易于阅读和编写,并具有更高的可移植性。 汇编语言的主要特点是:
原理性:汇编语言与机器语言直接相关,程序员需要了解CPU的结构以及CPU指令,来实现对计算机的底层操作。 直接性:汇编语言操作的是硬件资源,程序中直接控制了硬件的执行。 机器相关性:不同硬件和不同体系结构的计算机需要不同的汇编语言,并且同一架构下的不同类型的处理器也有不同的汇编语言。此外,编写汇编语言程序通常需要与处理器架构和操作系统的特定细节打交道。
虽然汇编语言编写程序的效率和可读性相对较低,但是它仍然在一些特定领域中使用广泛,如嵌入式系统、游戏开发、驱动程序编程等。
3.高级语言
高级语言是一类被设计用来编写计算机程序的程序设计语言。相比低级语言,高级语言更加抽象化,语法表述更加自然和易于阅读和编写,程序员可以更加关注程序的逻辑和业务流程,而不必关注计算机硬件的细节。高级语言通常具有更强的可移植性和易维护性。 高级语言的主要特点是:
程序员只需关注程序的逻辑和业务流程,而不是计算机硬件的细节。 可读性强,使用语法自然,易于编写、调试和维护,代码复杂度相对较低。 具有丰富的标准库和开发人员社区支持,可用于编写各种类型的应用程序。
常见的高级语言包括Java、C++、Python、JavaScript、Ruby等。高级语言的使用使得程序员能够更快速地开发出高质量、可靠的软件,并且可以跨越不同的平台进行开发。虽然高级语言语法复杂度比较低,但是高级语言运行速度相对低于低级语言。
二.编程范式
1.什么是编程范式
编程范式是指描述和规定程序结构和执行方式的一组原则和方法。一种编程范式定义了编程语言和编程工具的使用方式,以解决特定类型的问题。常见的编程范式包括:
面向过程编程(Procedural Programming):这是一种基于过程(函数或子程序)的编程方式,它将程序视为一系列相互关联的步骤,每个步骤都执行特定的操作。C语言就是一种面向过程编程语言。 面向对象编程(Object-oriented Programming,OOP):它将程序视为一组相互作用的对象,每个对象都具有自己的属性和行为。OOP编程中,类是一个模板,它定义了一组数据和操作,而对象则是该类的一个实例。Java和C++等语言是常见的面向对象编程语言。 函数式编程(Functional Programming):函数式编程是一种编写计算机程序的方式,其中函数是程序的基本构建块之一。在这种范式中,函数被视为一种数学函数(即没有任何状态或副作用),它通过接收输入和返回输出来执行计算。Lisp和Haskell是常见的函数式编程语言。 声明式编程(Declarative Programming):这种编程方式描述了“怎样做”,而不是“做什么”。它将程序视为一组约束或表达式,而不是一组指令。SQL是一种声明式编程语言,它使用查询语句来描述如何获取数据,而不是指定如何对数据执行操作。 并发编程(Concurrent Programming):并发编程是一种编写并发程序的方式,其中多个任务可以同时执行。它使用线程、进程和协程等机制来实现并发性。Python和Java等语言都提供了多线程编程的支持。
每种编程范式都有自己的优缺点和适用领域。选择合适的编程范式是根据具体需求和问题来决定的。
问题:面向过程编程有什么缺点?为什么后面会出现面向对象?
面向过程编程的缺点主要有以下几点:
1.数据与算法关联弱
2.不利于修改和扩充
3.不利于代码重用
为了解决这些缺点,面向对象编程(OOP)逐渐成为了主流。面向对象编程使用对象作为程序的基本单位,将数据和处理数据的方法组合在一起。这样可以更加方便的组织和维护代码,使代码的可读性、可扩展性和可重用性得到提高。 OOP采用的封装、继承和多态的特性,可以更加方便地进行代码的组合与重组,使程序更有弹性。而且面向对象编程中弱化了数据区和方法区之间的界限,增加了程序的灵活性和可读性。
面向对象编程
特点:
1.封装
2.继承
3.多态
4.依赖注入
原则:
面向对象编程(OOP)有五个基本原则,又称为SOLID原则,这些原则描述了良好的软件设计实践,同时也有助于开发出易于扩展和维护的高质量软件。
单一职责原则(Single Responsibility Principle,SRP):一个类或模块应该有且仅有一个责任,即应该只有一个原因导致它的变化。 开放封闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改的。 里式替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换掉它们的父类型。也就是说,在任何使用父类型对象的地方都应该能够使用其子类型对象。 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该被迫依赖它们不使用的接口。类之间的依赖关系应该建立在最小的接口上。 依赖反转原则(Dependency Inversion Principle,DIP):高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
这些原则可以帮助编程人员编写更加灵活、可扩展、可维护的代码,从而改进软件的设计和质量。
问题:面向对象编程的缺点?为什么要使用函数式编程?
面向对象编程的缺点有以下几点:
复杂性:面向对象编程通常会引入更多的概念和抽象,程序结构也更加复杂,因此在设计和维护过程中需要更多的工作量。 性能:面向对象编程通常比面向过程编程性能较低,因为它需要更多的内存和处理时间来实现对象创建和维护。 可变性:面向对象编程中对象的状态是可以随着时间变化的,这会引起一些难以预测的行为,比如不可预测的副作用等。 并发性:由于面向对象编程中对象的状态是共享的,因此在并发环境可能会带来一些问题。
函数式编程是一种基于数学函数的编程方式,它的主要特点是对状态的封闭和对数据的不可变性,这种方式不会引入副作用和数据竞争,可以提高代码的可读性、可维护性和可扩展性。此外,函数式编程还支持并行和异步执行,可以很好地适应现代计算机硬件发展的趋势。 因此,在解决某些问题的时候,使用函数式编程可以带来更好的效果。比如,在处理大规模数据集时,函数式编程可以有效地使用多核处理器提高程序的性能,同时也可以减少代码中的错误和难以调试的情况。
函数式编程
函数式编程(functional programming)是一种编写计算机程序的方式,其中函数是程序的基本构建块之一。在这种范式中,函数被视为一种数学函数,它通过接收输入和返回输出来执行计算。与面向对象编程(OOP)强调的是操作的对象不同,函数式编程强调数据输入到输出的转换过程,更关注过程本身而不是变量状态的变化。 函数式编程的主要特点如下:
纯函数(Pure function):一个函数在相同的输入下总是返回相同的输出,不依赖外部状态,也不会对外部状态造成影响。 不可变性(Immutability):函数式编程中使用不可变的数据结构,即一旦创建状态就无法更改,因此可以避免复杂的状态管理和数据竞争。 函数组合(Function composition):通过将函数组合起来,可以构造出更复杂的功能。 高阶函数(Higher order function):函数可以作为另一个函数的输入,也可以作为输出结果返回。 延迟计算(Lazy evaluation):函数式编程中,表达式不会立即计算,而是在需要计算时才进行计算。
函数式编程可以很好地处理并行计算、响应式编程、异步编程等场景,也可以帮助程序员编写更清晰、简洁、易于维护的代码。而且,函数式编程对于数学科学也有很强的联系,可以应用于许多数学和科学计算领域。常见的函数式编程语言包括Lisp、Haskell、Scala等。同时,Java和Python也提供了一些函数式编程的特性和库。
响应式编程
响应式编程(Reactive Programming)是一种针对异步数据流的编程范式,主要应用于事件驱动、消息推送、图形用户界面(GUI)、网络通信等需要处理异步数据的场景中。它的核心思想是将系统的所有组件都看作是数据的流动,并定义针对数据流的操作,以响应流中的事件和数据。 响应式编程的主要特点如下:
响应式(Responsive):响应式编程通过创建响应式数据流,使得应用程序能够更快地响应事件和数据。 异步(Asynchronous):响应式编程使用异步编程技术,避免了阻塞并且能更好地利用系统资源。 数据流(Data Flow):响应式编程通过将应用程序看作是数据流的方式,使得应用程序更具可预测性和可测试性。 订阅(Subscription):响应式编程运用订阅机制使得应用程序可以在数据流变化时获得通知。
常见的响应式编程框架有ReactiveX(RxJava、RxJS)、Spring Reactor、Akka Streams等。响应式编程可以提高应用程序的响应速度和可扩展性,同时通过流式编程的方式,提高了代码的可读性和可维护性。
领域特定语言
领域特定语言(Domain-Specific Language,DSL)是一种针对特定领域、问题或应用程序的编程语言,它的设计旨在简化问题领域中的特定任务及其相关的工具和技术。DSL通常是用于解决特定问题的小型语言,与大多数通用编程语言不同,常常只关注于解决小范围的问题,从而使得它们更加易于使用和理解。 DSL的使用可以提高生产效率、降低错误率,同时也可以增加代码的可读性和可维护性。DSL的种类有很多种,包括:
领域特定语言:针对特定领域的问题,通常包含相关领域的专业术语和语法。 内部领域特定语言:是一种在通用编程语言上构建的基于领域的语言,通常通过程序库和框架提供支持。内部DSL通常比独立的DSL更灵活和易于实现。 外部领域特定语言:是一种独立于通用编程语言的语言,通常需要设计和实现解释器或编译器。
常见DSL的种类包括配置语言、模板语言、查询语言、规则语言等。DSL的优点在于可以让开发者使用一种更加贴近问题领域的语言来解决领域问题,而不是使用通用编程语言。这样可以提高开发者的生产效率和程序的可维护性,同时还可以提高程序的可靠性和性能。
创造DSL
创造领域特定语言(DSL)可能会涉及到以下几个步骤:
定义问题领域和范围:首先需要定义和限制问题领域和范围,在此基础上选择和设计特定领域的语言。 定义语言结构:根据问题领域的特点,定义合适的语言结构,包括语法、关键字等。 实现语言解析器或编译器:根据语言结构,实现相应的解析器或编译器,解析用户输入的程序,并转换为可执行代码或中间表示。 测试和调试:对于新开发的语言,需要进行性能测试和各种错误情况的测试,以保证语言的正确性和稳定性。 发布和使用:通过文档、示例和工具支持等方式,发布语言,并鼓励用户使用该语言解决相应领域的问题。
在设计DSL时,需要设计一个易于使用和理解的语言,最好能够与目标用户习惯的工具和方法自然衔接。另外,如果选择在已有通用编程语言上实现内部DSL,需要注意保证DSL代码的可读性和可维护性,避免过度依赖内部DSL的语法和底层实现。