最近,我被分配了一项任务,即使用面向对象编程来创建具有加,减,乘,除和乘幂功能的计算器。我成功完成了这项任务。但是之后,我重新编程了整个程序,而没有使用面向对象的技术/方法。
我注意到我的代码长度大大减少了,这是可以理解的。所以我的问题是,什么时候应该使用面向对象编程?是否可以使用面向对象的语言来创建没有面向对象的程序?请帮助我解决这一问题。
PS:我不是要在这里告诉我面向对象编程优于过程编程的优点。
最近,我被分配了一项任务,即使用面向对象编程来创建具有加,减,乘,除和乘幂功能的计算器。我成功完成了这项任务。但是之后,我重新编程了整个程序,而没有使用面向对象的技术/方法。
我注意到我的代码长度大大减少了,这是可以理解的。所以我的问题是,什么时候应该使用面向对象编程?是否可以使用面向对象的语言来创建没有面向对象的程序?请帮助我解决这一问题。
PS:我不是要在这里告诉我面向对象编程优于过程编程的优点。
Answers:
C ++不只是“一种” OO语言,它还是一种多范式语言。因此,它使您可以决定是否支持OO编程,或将二者混合使用。使用OO技术可以为程序增加更多结构-当程序达到一定大小或复杂度时,您将从中受益。但是,这种额外的结构是以额外的代码行为代价的。因此,对于“小型”程序来说,最好的方法通常是首先以非OO风格实施它们,然后在程序开始发展多年后,再添加越来越多的OO技术(“练习”可能不会发生)。 ”程序,但这是许多业务程序的典型生命周期)。
棘手的部分是不要错过程序复杂性达到要求更多结构的大小的时间点。否则,您将获得大量的意大利面条代码。
专业程序员如何判断是否要进行OOP?这对我真的很有帮助。
对我来说,有两个决定点。首先,有时一开始就会很明显。将会有很多相似的类型,它们都共享在实现细节上差异很大的通用方法。例如,我正在构建工作流系统,并且我需要能够执行任意任务。为了运行任务,我使用Execute()
抽象方法实现了每个任务都继承自的基类。继承的类提供了实现,但是工作流系统可以在不知道正在运行哪种任务的情况下开始执行。
但是,大多数项目并没有那么明确。第二个决策点是,当项目的一个子集变成大量的if-then语句或switch-case语句时,特别是当这些if-then语句需要大量安装代码才能正确运行时。我感到自己开始迷失自己想要完成的工作的逻辑,并且代码开始变得脆弱。到那时,通常标志着是时候将代码重构为具有特定实现的基类了。
切换到面向对象样式而不是功能样式的很大一部分是将if-then语句转换为“运行此操作”语句。您无需告诉大量的if-then语句,而是告诉代码运行其动作。实际执行哪个操作取决于您提供的实现。
例如,这是C#风格的伪代码的功能风格:
if ( action == "email" ) {
callEmailFunction(userInfo);
}
else if ( action == "sms" ) {
callSmsFunction(userInfo);
}
else if ( action == "web" ) {
endpoint = "http://127.0.0.1/confirm";
confirmWeb(endpoint, userinfo);
}
...
但是也许您可以将其重写为如下形式:
interface IConfirmable {
void Confirm(UserInfo userinfo);
}
public class ConfirmEmail : IConfirmable {
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via email
}
}
public class ConfirmSms : IConfirmable {
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via email
}
}
public class ConfirmWeb : IConfirmable {
// this is a constructor
public ConfirmWeb(string endpoint) {
...
}
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via web
}
}
然后代码本身:
// An implementation that decides which implementation of the base class to use
// This replaces the if-then statements in the functional programmming.
IConfirmable confirmer = ConfirmerFactory.GetConfirmer();
// get the userinfo however you get it,
// which would be the same way you get it in the functional example.
UserInfo userinfo = ...;
// perform the action.
confirmer.Confirm(userinfo);
现在,如果if-then内的代码很少,这似乎需要花费很多精力。而且,如果if-then中的代码很少,那是正确的:对于难以理解的代码,这需要大量工作。
但是,当您有多个动作而不只是Confirm()
需要执行的方法时,面向对象的样式确实会发光。也许您有一个初始化例程,三个或多个可以运行的动作方法以及一个Cleanup()
方法。基本算法是相同的,不同之处在于它对实现通用基类的适当对象进行了调用。现在,您开始看到面向对象样式的真正好处:与在每个步骤中检查if-then语句相比,基本算法更易于阅读。
var dict = new Dictionary<string,Action<UserInfo>{ { "email", callEmailFunction }, { "sms", callSmsFunction } }; dict[ action ]( userInfo );
(dict可以是静态的,省略了错误处理)
是的,只要您的项目范围众所周知或受到限制,使用旧样式代码是完全正常的。如果您打算扩展程序或项目,那么OOP是一种方法,因为您可以无缝地维护和扩展代码,另一方面,如果您计划了代码,并且得出的结论是,您永远不会计划扩展程序的可扩展性。您进行的项目,然后编写没有OOP的代码就足够了。这并不意味着如果您使用非OOP方法就永远无法升级项目,但这将是一件乏味的事情。OOP可以帮助我们将我们的概念形象化,就像它是现实生活中的有机体一样,因为我们对这些概念的了解比其他任何事物都更好。