软件工程

针对在系统开发生命周期中工作的专业人士,学者和学生的问答

10
使用指针变量不是内存开销吗?
在C和C ++之类的语言中,使用指向变量的指针时,我们还需要一个内存位置来存储该地址。那这不是内存开销吗?如何补偿?时间紧迫的低内存应用程序中使用指针吗?
29 c++  c  pointers 

15
在现代计算时代,在“典型业务应用程序”中-为什么性能很重要?[关闭]
对于某些人来说,这似乎是一个奇怪的问题。 我是一名业余Java程序员。我已经开发了几个游戏,一个可以创建音乐的AI程序,另一个用于绘画的程序以及类似的东西。这是要告诉您,我有编程经验,但是没有业务应用程序的专业开发经验。 我在这个网站上看到了很多有关性能的话题。人们经常争论什么是C#中执行任务的最有效算法,或者为什么Python速度慢而Java速度更快等。 我想了解的是:为什么这很重要? 在某些特定的计算领域中,我明白了性能为何如此重要:游戏,在一个恒定更新循环中每秒发生成千上万次计算,或者其他程序所依赖的低级系统,例如OS和VM等。 但是对于普通的,典型的高级商务应用程序,为什么性能很重要? 我能理解几十年前为什么如此重要。计算机的速度要慢得多,内存也要少得多,因此您必须仔细考虑这些事情。 但是今天,我们有太多的可用内存可供使用,并且计算机是如此之快:如果特定的Java算法为O(n ^ 2),这实际上有关系吗?对于这个典型的商业应用程序的最终用户而言,这实际上会有所不同吗? 在现代计算的当今时代,当您在典型的业务应用程序中按GUI按钮并在后台调用O(n ^ 2)算法时,您实际上是否感到效率低下? 我的问题分为两部分: 在实践中,今天的业绩对典型的正常业务计划是否重要? 如果是这样,请给我提供此类应用程序中性能和优化很重要的位置的真实示例。

3
如何在Redis上实现消息队列?
为什么要对Redis进行排队? 我的印象是Redis可以很好地实现排队系统。到目前为止,我们一直在使用MySQL数据库进行轮询或RabbitMQ。有了RabbitMQ,我们遇到了很多问题-客户端库非常差且存在漏洞,我们不想花费太多的开发人员时间来修复它们,也不希望在服务器管理控制台上遇到一些问题,等等。至少,我们没有掌握几毫秒,也没有认真提高性能,因此,只要系统的体系结构能够智能地支持队列,我们​​就可能处于良好状态。 好的,这就是背景。本质上,我有一个非常经典,简单的队列模型-几个生产者在生产工作,几个消费者在消费工作,生产者和消费者都需要能够智能地进行扩展。事实证明,天真PUBSUB是行不通的,因为我不希望所有订阅者都消费工作,我只希望一个订阅者可以接收工作。乍一看,在我看来,这BRPOPLPUSH是一个明智的设计。 我们可以使用BRPOPLPUSH吗? 基本设计BRPOPLPUSH是您有一个工作队列和一个进度队列。当消费者收到工作时,它会自动将项目推送到进度队列中,而当工作完成时,它就是工作LREM了。如果客户死了,这可以防止工作混乱,并使监视工作变得很轻松-例如,我们可以判断是否存在导致消费者花费大量时间来执行任务的问题,此外还可以判断是否存在大量任务。 它确保 作品交付给了一位消费者 工作在进度队列中结束,因此如果消费者使用它,则不会出现黑洞 缺点 对于我来说,我发现的最好的设计实际上没有使用实际上是很奇怪的,PUBSUB因为这似乎是大多数有关Redis排队的博客所关注的内容。所以我觉得我缺少明显的东西。我看到PUBSUB不使用两次任务就使用的唯一方法是简单地推送一个通知,通知工作已经到达,然后消费者可以无阻塞地进行通知RPOPLPUSH。 一次请求一个以上的工作项目是不可能的,这似乎是一个性能问题。对于我们的情况而言,这不是一个很大的选择,但显然,该操作不是针对高吞吐量或这种情况而设计的 简而言之:我是否缺少任何愚蠢的东西? 还添加了node.js标记,因为这是我最常使用的语言。考虑到Node的单线程和非阻塞性质,它可能会在实现方面提供一些简化,但是此外,我正在使用node-redis库,并且解决方案也应该或可以对其优点和缺点敏感。

5
这是否是识别算法的“大O”符号的正确“规则”?
我一直在学习有关大O表示法的更多信息,以及如何根据算法编写方式对其进行计算。我遇到了一组有趣的“规则”,用于计算算法“大O”表示法,我想看看自己是在正确的轨道上还是在正确的道路上。 大O表示法:N function(n) { For(var a = 0; i <= n; i++) { // It's N because it's just a single loop // Do stuff } } 大O表示法:N 2 function(n, b) { For(var a = 0; a <= n; a++) { For(var c = 0; i <= b; c++) { …
29 algorithms  big-o 

9
为什么大多数“知名”命令式/ OO语言都允许未经检查的类型代表“无”值的访问?
我一直在阅读关于拥有null而不是(例如)的(不便)便利的信息Maybe。阅读本文之后,我相信使用Maybe(或类似方法)会更好。但是,令我惊讶的是,所有“众所周知”的命令式或面向对象的编程语言仍在使用null(这允许对可以表示“无”值的类型进行未经检查的访问),并且Maybe大多数在函数式编程语言中使用。 作为示例,请看下面的C#代码: void doSomething(string username) { // Check that username is not null // Do something } 这里有些难闻的气味...为什么我们要检查参数是否为null?我们不应该假设每个变量都包含对对象的引用吗?如您所见,问题在于,根据定义,几乎所有变量都可以包含空引用。如果我们可以决定哪些变量是“可为空的”而哪些则不是呢?这将节省我们调试和寻找“ NullReferenceException”时的工作量。想象一下,默认情况下,没有类型可以包含null引用。取而代之的是,您将明确声明变量只有在确实需要时才可以包含空引用。那就是Maybe背后的想法。如果您的函数在某些情况下会失败(例如,被零除),则可以返回Maybe<int>,明确指出结果可能是整数,但也没有任何结果!这是选择Maybe而不是null的原因之一。如果您对更多示例感兴趣,那么我建议阅读这篇文章。 事实是,尽管存在使大多数类型默认为可空的缺点,但大多数OO编程语言实际上都可以做到这一点。这就是为什么我想知道: 您必须用null编程语言来实现什么样的参数Maybe呢?完全有原因还是仅仅是“历史包bag”? 在回答此问题之前,请确保您了解null和Maybe之间的区别。


2
这些常见的对口齿不清的旧批评在今天仍然适用?
在1984年由Stanford的Rodney A. Brooks和Richard P. Gabriel撰写的“ Common Lisp批判”中,讨论了Common Lisp规范化委员会保留的一些设计决策。尽管大多数讨论仍然有效,但是有两种说法是指当时可用的技术,今天可能是错误的。 这两个语句是: 由于“任何好的编译器”都可以照顾到这种语言,因此消除了这种语言的太多成本。到目前为止,还没有人编写过(即使没有付出巨大的努力也不会编写)一种编译器,该编译器完成了预期的技巧。 由于我是Lisp的新手,甚至是学徒,因此我无法比作者更具体。他们似乎指出,该语言的多个方面已经内置了极大的通用性和灵活性,这使得编写一个好的编译器非常困难。 在COMMON LISP中,对浮点算法的控制太多了。当然,尽管可以获得浮点密集型程序的正确行为,但性能可能会发生巨大变化。 据我了解,用Common Lisp编写高效的数字代码似乎是可能的,但比必须的更具挑战性。 那是三十年前。如果我愿意为一种常见的自由软件实现(CLISP,SBCL等)编写Common Lisp程序,我今天应该如何看待这些声明?


7
“数据隐藏”和“封装”有什么区别?
我正在阅读“实践中的Java并发性”,有人说:“幸运的是,相同的面向对象技术可以帮助您编写组织良好,可维护的类(例如封装和数据隐藏),也可以帮助您创建线程安全的类。” 问题#1-我从未听说过数据隐藏,也不知道它是什么。 问题2-我一直认为封装使用的是私有vs公共,实际上是在隐藏数据。 您能否解释一下什么是数据隐藏以及它与封装有何不同?

9
纯Java网络浏览器,实用吗?[关闭]
我知道可以使用Java Web浏览器,但是实用吗?我看过Lobo项目,必须承认我印象深刻,但是从我看来,该开发在2009年停止了。使用纯Java编码的浏览器(没有任何类型的WebKit Java绑定)能够与之抗衡吗?那些在Chrome或Firefox中名列前茅的产品,还是会固有地变慢,从而阻碍用户?
29 java  web  browser 

5
Java / C#为什么不能实现RAII?
问题:Java / C#为什么不能实现RAII? 澄清:我知道垃圾收集器不是确定性的。因此,使用当前的语言功能,不可能在范围出口处自动调用对象的Dispose()方法。但是,可以添加这种确定性功能吗? 我的理解: 我认为RAI​​I的实现必须满足两个要求: 1.资源的生存期必须绑定到范围。 2.隐式的。必须在没有程序员明确声明的情况下释放资源。类似于垃圾回收器无需显式语句即可释放内存。“隐含性”仅需要在使用该类时发生。当然,类库创建者必须显式实现析构函数或Dispose()方法。 Java / C#满足点1。在C#中,可以将实现IDisposable的资源绑定到“使用”范围: void test() { using(Resource r = new Resource()) { r.foo(); }//resource released on scope exit } 这不满足第2点。程序员必须将对象明确绑定到特殊的“使用”范围。程序员可能(并且确实)忘记将资源显式绑定到作用域,从而造成泄漏。 实际上,“使用”块已由编译器转换为try-finally-dispose()代码。它具有与try-finally-dispose()模式相同的显式性质。如果没有隐式发布,则作用域的钩子就是语法糖。 void test() { //Programmer forgot (or was not aware of the need) to explicitly //bind Resource to a scope. Resource r …

4
如何制止镀金并满足于发布工作进展
我所属的开发团队最近适应了敏捷实践的工作。这个人突出地表明了一个事实,就是我无法停止自己的镀金代码(和文档),因此,当我可以更早地交付满足要求的解决方案时,我就超出了最初的估计。 我认为我的道德观念与强迫症接壤,因为我过于依赖自己的代码,在重构和完善到第n级之前,很少满足于发布。我很高兴自己意识到了这一点,但是我如何才能改变自己的态度/心态来满足自己的进步并按时发布呢?

11
您最好的程序员是否应该将其他所有人的代码检入源代码控制中?
svn和git之间的区别之一是控制对存储库的访问的能力。很难将二者进行比较,因为对于完全应该允许谁提交更改的观点存在差异! 这个问题是关于将git用作某个公司的团队的集中存储库。假设团队成员的技能水平各不相同,这与大多数公司中的情况大同小异。 Git似乎假设只有最好的(最有生产力,最有经验的)程序员才能签入代码。如果是这种情况,您将他们的时间花在了编写实际代码以检查其他人的代码以进行检入方面。我真的想将这个问题的重点放在最佳程序员时间的最佳利用上,而不是一般的最佳版本控制实践上。一个必然的结果是,如果优秀的程序员的大部分工作是检查他人的代码,他们会辞职吗?我认为这两个问题都归结为:审查是否值得提高生产力?

6
我应该将特定功能提取到功能中,为什么?
我有一个执行3个任务的大型方法,每个任务都可以提取到一个单独的函数中。如果我将为每个任务添加其他功能,那么它会使我的代码变得更好还是更坏,为什么? 显然,它将在主函数中减少代码行的数量,但是将有附加的函数声明,因此我的类将具有附加的方法,我认为这不好,因为这会使类变得更加复杂。 我应该在编写所有代码之前执行此操作,还是在完成所有操作然后提取函数之前将其保留?

3
查看单子的不同方法
在学习Haskell的过程中,我遇到了很多教程,试图解释什么是monad,以及为什么monad在Haskell中很重要。他们每个人都使用类比,因此更容易理解其含义。归根结底,我对单子是3种不同的看法: 查看1:将Monad作为标签 有时我认为将monad作为特定类型的标签。例如,一个类型的函数: myfunction :: IO Int myfunction是一个函数,无论何时执行它都会产生一个Int值。结果的类型不是Int,而是IO Int。因此,IO是Int值的标签,警告用户知道Int值是执行IO操作的过程的结果。 因此,此Int值已被标记为来自具有IO的过程的值,因此该值为“脏”。您的过程不再是纯粹的。 视图2:莫纳德(Monad)是可能发生令人讨厌的事情的私人空间。 在所有过程都是纯且严格的系统中,有时您需要产生副作用。因此,monad只是一个很小的空间,允许您做讨厌的副作用。在这个空间中,您可以逃脱纯净的世界,走不纯净的事物,进行过程,然后返回有价值的东西。 图3:Monad的范畴论 我不完全理解这种观点。monad只是同一类别或子类别的函子。例如,您具有Int值,并且作为IO Int子类,它们是在IO过程之后生成的Int值。 这些观点正确吗?哪个更准确?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.