软件工程

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

3
Ruby创建者为什么选择使用符号的概念?
tl; dr:是否会有语言不可知的符号定义,以及是否有其他语言的符号? 那么,为什么Ruby创建者symbols在语言中使用的概念? 我是从非橄榄球程序员的角度提出这个问题的。我学习了许多其他语言,但没有发现需要指定我是否在处理Ruby所调用的语言symbols。 主要的问题是, symbols Ruby存在以提高性能,还是仅仅因为语言的编写方式而需要? Ruby中的程序会比Python或Javascript对应的程序轻和/或快吗?如果是这样,那是因为symbols吗? 由于Ruby的目的之一是易于人类阅读和编写,难道其创建者不能通过在解释器本身中实现这些改进来简化编码过程吗(就像其他语言一样)? 似乎每个人都只想知道symbols它们是什么以及如何使用它们,而不是为什么首先要知道它们的存在。

3
如何在客户端/服务器实时视频游戏中处理速度更快的计算机
我正在使用socket.io创建我的第一个在线游戏,我希望它是像agar.io或diep.io这样的实时多人游戏。 但是我遇到了试图弄清楚如何使所有计算机以相同速度工作的问题。 我对模型有三个想法,但似乎都不对,我想知道普通电子游戏是如何做到的。(您可以跳过阅读我的想法;它们只是给您一种查看我遇到的问题的方法。) 服务器允许客户端自行运行,并将更新传递给服务器,然后服务器将其广播给其余的客户端。这样做的问题是,某些计算机的运行速度比其他计算机要快,因此它们的更新速度更快,并且在屏幕上的移动速度更快。 让服务器告诉客户端何时更新。然后,我可以等到最后一个客户端做出响应(如果一个人的计算机速度较慢,这是一个糟糕的主意),或者等到第一个客户端做出响应(再次,在每帧之前等待通信),或者尽可能快地发送它们(似乎遇到了与数字1相同的问题。 在游戏开始时,让服务器告诉客户端更新的速度。这意味着客户将负责限制这段时间之间的移动。例如,如果某人设法在该时间段内两次按下按钮,则只会发送一个按钮按下事件。这样做的问题是某些操作将被忽略(例如,按两次双键),并且交互将依赖于客户端的时钟,而这可能与服务器的时钟不匹配。然后,服务器将必须跟踪每个客户端,并确保在正确的时间提交其更新。 我已经进行了一些研究,但是我阅读的文章似乎并未具体说明如果客户端发送更新的速度比其他客户端快的话该怎么办。 在我的特定情况下,我正在与键盘速度更快的人打交道(他们的计算机比其他计算机发送更多的键盘更新)。 程序员通常如何处理呢?


6
编写源代码时如何遵循80个字符限制的最佳做法?
如您所知,有一个最佳做法是 一行源代码限制为80个字符。 这里有2个链接: 为什么80个字符是代码宽度的“标准”限制? 在宽屏显示器时,80个字符的限制是否仍然有用? 而且,我敢肯定,如果您搜索此最佳做法,可以做得更好。 但是我发现这非常困难,这是一个示例示例: public class MyClass { public void myMethod() { final Map<String, List<MyInterfaceHere>> myReference 因此,您可以缩进每个类,每个方法和每个语句。 在“ myReference”中最后一个“ e”的结尾,我已经在第60列了。 我还有20个空格,实际上是要调用构造函数并将对象分配给我拥有的引用。 我的意思是,这看起来真的更好吗: public class MyClass { public void myMethod() { final Map<String, List<MyInterfaceHere>> myReference = new HashMap<String, List<MyInterfaceHere>>(); 最佳做法是什么?

7
在使用整数(例如在For循环中)时是否应避免<=和> =?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 3年前关闭。 我已经向我的学生解释说,等于测试对于浮点变量并不可靠,但对于整数则可以。我使用的教科书说&gt;和&lt;比&gt; =和&lt;=更容易阅读。我在某种程度上同意,但是在For循环中?让循环指定开始和结束值是否更清晰? 我是否缺少教科书作者正确的东西? 另一个示例在范围测试中,例如: 如果分数&gt; 89等级='A' 否则,如果分数&gt; 79等级='B'​​... 为什么不直接说:如果分数&gt; = 90?
15 loops 

3
长期运行未发布代码的Git分支策略
在我们的团队中,除了个别的工作单元(故事),我们还有工作时间更长的主题(史诗)。多个故事成为史诗。 传统上,我们为每个故事提供功能分支,并在它们通过质量检查后直接合并为母版。但是,我们希望开始阻止在Epic中发布已完成的故事,直到Epic被视为“功能已完成”为止。我们只会在整个Epic关闭时才将这些功能发布到生产环境中。此外,我们有一个每晚生成的服务器-我们希望所有封闭的Stories(包括那些不完整的Epics的故事)都将自动部署到该每晚的服务器。 关于如何管理我们的仓库来实现这一目标,有什么建议吗?我考虑过引入“史诗般的分支”,在这里我们将封闭的故事合并到相关的史诗分支中,而不是直接掌握。但我担心的是: 我担心如果史诗分支长时间保持开放可能会发生合并冲突 每晚构建需要将所有史诗分支合并为一个“每晚构建”分支。同样,可能会发生合并冲突,这将自动完成

8
我应该在抛出异常的构造函数上记录错误吗?
我花了几个月的时间来构建应用程序,然后才发现出现了一种模式: logger.error(ERROR_MSG); throw new Exception(ERROR_MSG); 或者,在捕捉时: try { // ...block that can throw something } catch (Exception e) { logger.error(ERROR_MSG, e); throw new MyException(ERROR_MSG, e); } 因此,无论何时我抛出或捕获异常,都将其记录下来。实际上,这几乎是我在应用程序上所做的所有日志记录(除了一些用于应用程序初始化的操作)。 因此,作为一名程序员,我避免重复。因此,我决定将logger调用移至异常构造,因此,每当构建异常时,都会记录事件。当然,我也可以创建一个ExceptionHelper来为我抛出异常,但是这会使我的代码更难以解释,更糟糕的是,编译器无法很好地处理它,而没有意识到对该成员的调用会立即扔。 那么,这是一种反模式吗?如果是这样,为什么?

2
应该从std :: exception派生/继承吗?
在设计我的第一个“严肃的” C ++库时,我在问自己: 从中衍生出某些例外std::exception是后代吗? 即使阅读后 设计异常类 为我的图书馆实施的“异常数量”是多少? 我还不确定。因为,除了常见的(但可能不是很好)的做法之外,我将以库用户的身份假设,std::exception仅当标准库函数在库实现中失败时,库函数才会抛出s,而它对此无能为力。但仍然,在编写应用程序代码时,对我来说非常方便,并且恕我直言,好看的只是抛出一个std::runtime_error。另外,我的用户还可以依赖定义的最小接口,例如what()或代码。 例如,我的用户提供了错误的参数,比抛出a更方便std::invalid_argument吗?因此,与在其他代码中看到的std :: exception的常用用法结合在一起:为什么不走得更远,从您的自定义异常类(例如lib_foo_exception)以及std::exception。 有什么想法吗?
15 c++  exceptions 

4
API和函数式编程
从我(有限地)接触函数式编程语言(例如Clojure)开始,似乎数据封装的作用不那么重要。通常,各种本机类型(例如地图或集合)是代表对象的首选数据。此外,该数据通常是不可变的。 例如,这是Clojure的成名人物里奇·希基(Rich Hickey)在接受此事采访时最著名的名言之一: Fogus:遵循了这个想法,Clojure并未对其类型进行数据隐藏封装,这一事实使某些人感到惊讶。您为什么决定放弃数据隐藏? Hickey:让我们清楚一点,Clojure强烈强调对抽象的编程。但是在某个时候,某人将需要访问数据。而且,如果您有“私有”的概念,则需要相应的特权和信任的概念。这就增加了很多复杂性和很小的价值,在系统中产生了僵化,并常常迫使事物生活在不应有的地方。这是将简单信息放入类时发生的其他损失的补充。在某种程度上,数据是不可变的,提供访问的危害很小,除了有人可能会依赖可能发生变化的事物之外。好吧,好吧,人们在现实生活中一直如此,当事情发生变化时,他们就会适应。如果他们是理性的,他们知道,当他们基于可能会改变的事物做出决定时,将来可能需要适应。因此,这是一项风险管理决策,我认为程序员应该可以自由做出。如果人们不希望对抽象编程,也不愿意与实现细节相结合,那么他们永远都不会成为优秀的程序员。 来自面向对象的世界,这似乎使我多年来学到的一些基本原则变得复杂。其中包括信息隐藏,德米特定律和统一访问原则等。封装的共同点是使我们能够为其他人定义API,让他们知道应该和不应该接触的内容。从本质上讲,创建一个合同,允许某些代码的维护者自由地进行更改和重构,而不必担心它将如何在用户代码中引入错误(开放/封闭原则)。它还为其他程序员提供了一个干净,精心设计的界面,以使他们知道可以使用哪些工具来获取或建立该数据。 当允许直接访问数据时,该API合同被破坏,所有这些封装好处似乎都消失了。同样,严格不变的数据似乎在遍历特定于域的结构(对象,结构,记录)时,在表示状态和可以对该状态执行的操作的意义上要有用得多。 当代码库的大小变得巨大而需要定义API且许多开发人员参与处理系统的特定部分时,功能代码库如何解决似乎出现的这些问题?是否存在这种情况的示例,以说明在这些类型的代码库中如何处理此情况?

2
可以避免测试基类吗?
我有一个带有大量“元编程”的基类,以使其具有相当通用的灵活性/抽象性。 在基类中,我确实有很多使用通用方法的子类,并且有面向行为的单元测试,涵盖了每个子类中的所有情况。 可以跳过基类测试吗?

4
OOP应用程序中的参数管理
我正在用C ++编写一个中等大小的OOP应用程序,作为实践OOP原理的一种方法。 我的项目中有几个类,其中一些需要访问运行时配置参数。这些参数是在应用程序启动期间从多个来源读取的。有些是从用户home-dir中的配置文件读取的,有些是命令行参数(argv)。 所以我创建了一个类ConfigBlock。此类读取所有参数源并将其存储在适当的数据结构中。示例是路径和文件名,用户可以在配置文件或--verbose CLI标志中更改它们。然后,可以调用ConfigBlock.GetVerboseLevel()以读取此特定参数。 我的问题:在一个类中收集所有此类运行时配置数据是一种好习惯吗? 然后,我的班级需要访问所有这些参数。我可以想到几种方法来实现这一目标,但是我不确定该采取哪种方法。类的构造函数可以是对我的ConfigBlock的给定引用,例如 public: MyGreatClass(ConfigBlock &amp;config); 或者,它们仅包含标头“ CodingBlock.h”,其中包含我的CodingBlock的定义: extern CodingBlock MyCodingBlock; 然后,仅类.cpp文件需要包含和使用ConfigBlock内容。 .h文件不会将此接口引入类的用户。但是,ConfigBlock的接口仍然存在,但是从.h文件中隐藏了该接口。 这样隐藏起来好吗? 我希望接口尽可能小,但最后,我想每个需要配置参数的类都必须与我的ConfigBlock连接。但是,这种连接应该是什么样的?

6
策略模式的优势
如果仅在if / then情况下编写代码,使用策略模式为什么有好处? 例如:我有一个TaxPayer类,它的一种方法使用不同的算法来计算税收。那么,为什么不具有if / then情况并找出在该方法中使用哪种算法而不是使用策略模式呢?另外,为什么不能只为TaxPayer类中的每个算法实现单独的方法? 另外,算法在运行时更改意味着什么?


1
消费者/生产者与观察者/可观察者之间的差异
我正在设计一个包含三个部分的应用程序: 监视某些事件(文件创建,外部请求等)发生的单个线程 N个工作线程通过处理它们来响应这些事件(每个工作进程处理并消耗一个事件,并且处理可能需要花费可变的时间) 一个控制器,用于管理那些线程并执行错误处理(线程重新启动,结果记录) 尽管这是非常基本的,并且不难实现,但我想知道这样做的“正确”方法是什么(在Java的这种具体情况下,但也希望有更高的抽象答案)。我想到两种策略: 观察者/可观察者:监视线程由控制器观察。在发生事件的情况下,然后会通知控制器,并可以将新任务分配给可重用的缓存线程池中的空闲线程(如果所有线程当前都忙,请等待并将任务缓存在FIFO队列中)。工作线程实现Callable并返回结果(或布尔值)成功或返回错误,在这种情况下,控制器可以决定要执行的操作(取决于发生的错误的性质)。 生产者/消费者:监视线程与控制器(事件队列)共享一个BlockingQueue,并且控制器与所有工作器(任务队列和结果队列)共享两个。在发生事件的情况下,监视线程将任务对象放入事件队列中。控制器从事件队列中获取新任务,对其进行审阅并将其放入任务队列中。每个工作人员都在等待新任务,并从任务队列中获取/使用它们(先到先服务,由队列本身进行管理),然后将结果或错误放回到结果队列中。最后,控制器可以从结果队列中检索结果,并在出现错误的情况下采取相应的步骤。 两种方法的最终结果是相似的,但是它们都有细微的差别: 使用观察者,线程的控制是直接的,每个任务都归属于特定的新生成的工作程序。创建线程的开销可能更高,但是由于缓存了线程池,因此开销并不大。另一方面,“观察者”模式被简化为单个“观察者”模式,而不是多个观察者模式,这与其设计的目的不完全相同。 队列策略似乎更容易扩展,例如,添加多个生产者而不是一个生产者很简单,不需要任何更改。不利之处在于,即使根本不做任何工作,所有线程也将无限期运行,并且错误/结果处理看起来不像第一个解决方案那样优雅。 在这种情况下最合适的方法是什么?为什么?我发现很难在线找到该问题的答案,因为大多数示例仅处理明确的案例,例如用“观察者”案例更新许多具有新值的窗口或与多个消费者和生产者进行处理。任何输入,不胜感激。

5
如何对待用户认为是功能的错误?
问题: 解决最终用户认为是功能的错误的正确方法是什么? 详细说明: 我猜想,如果很大一部分用户希望将其作为一项功能,应该将其“未固定”还是“固定”才能更稳定?但是,如果很少的用户期望它是一项功能,例如0.1%或1%,该错误必须得到解决。 从理论上讲,由于这是一个较小的错误修复程序,因此按语义版本控制考虑,它可以称为PATCH:xyZ但是,由于它确实破坏了向后兼容性(即使仅针对少数用户),因此应该是主要的提高:Xyz正确吗?只要有文件记载,它是否仍可以称为PATCH(因为它原本不是功能)? 编辑:在这种特定情况下,这是其他开发人员使用的内部使用库的API中的错误。

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.