软件工程

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

8
例如,对于大型Web应用程序,在现实世界中使用“强”类型系统吗?
我知道这是一个非常广泛,模棱两可甚至是哲学上的问题。在某种程度上,问题中最重要的关键字-“强”类型系统-本身定义不正确。所以,让我尝试解释我的意思。 问题的总体背景 我们已经在Ruby on Rails中构建了一个非常大型的Web应用程序,并且总体上我们对我们的堆栈感到满意。如果需要的话,我们可以非常快速地发货-可以在90%的“业务”案例中使用,而不必担心10%的边缘案例。另一方面,借助代码审查和测试覆盖率,我们可以缓慢而谨慎地进行,并确保覆盖所有基础-再次,仅在需要进行更仔细检查和安全的情况下。 但是,随着团队的壮大,我开始感到不舒服,因为缺少直接放入我们堆栈中的“安全网”。 我们最近开始在Java上进行一些本机Android开发。我(愉快地)想起了编译/静态/强类型语言提供的安全性。 IDE本身会捕获错误拼写的变量,错误的数据类型,错误的函数调用以及许多琐碎的错误。全部是因为IDE可以挂接到编译器并验证程序“正确性”的某些方面。 是否需要更改功能签名?简单。编译器+ IDE可以帮助您发现所有调用站点。 是否需要确保始终处理某些异常?已检查的救援例外情况。 现在,尽管这些安全功能各有优点,但我也很清楚它们的缺点。更重要的是,在“繁重的” Java世界中。因此,代替Java,我开始研究人们近来开始使用的大量现代“强类型”语言。例如:Scala,Rust,Haskell等。我最感兴趣的是它们的类型系统和静态/编译时检查的功能。 现在,问题 如何在大型应用程序中使用这些功能强大的类型系统和静态/编译时功能? 例如,对于这些强大的功能,我将如何超越标准的“ hello world”介绍?使用富类型系统来建模业务域问题的模型吗?当您位于30,000 LOC +区域中时,类型系统会帮助还是阻碍?当您的系统与弱类型的外部环境交互时,这些类型的系统(和编译时检查)所提供的安全网会如何处理?通过JSON或XML API,各种数据存储,用户输入等。

7
是否有任何算法模式可以保护网络上的任何内容,以确保我是第一个创建该内容的人?
几年前,有一位黑客(不记得他是谁)完全披露了给定系统中的漏洞,但为了确保没人对此表示赞赏,他创建了某种PGP密钥。 我当时的理解是,他创建了一个密钥以确保自己是发现它的那个人,但是没有透露自己的真实身份,只是创建了一种机制来证明他是那个创建披露的人。 。 好。我了解算法和密码学的工作原理。但是我仍然不明白如何创建一个密钥来保护网络上公开的给定内容,以证明您是最先创建它的人!这只是言语! 真的有可能吗?确保您可以凭经验证明的过程应该是什么?我是否理解正确,或者可能错过了一些与此案有关的东西? 我希望这个问题足够具体,基本上就是如何保护您在网络上创建的内容(一段,一段代码,一个单词等),并确保您是第一个创建该内容的人。给定上下文。 据我所知,我不知道这是怎么可能的,但是我对是否有可行的方法很感兴趣。在那儿?

6
创建新对象还是重置每个属性?
public class MyClass { public object Prop1 { get; set; } public object Prop2 { get; set; } public object Prop3 { get; set; } } 假设我有一个对象myObject,MyClass并且需要重置其属性,那么创建一个新对象或重新分配每个属性会更好吗?假设我对旧实例没有任何其他用途。 myObject = new MyClass(); 要么 myObject.Prop1 = null; myObject.Prop2 = null; myObject.Prop3 = null;

10
Java中的模板“元编程”是个好主意吗?
在一个相当大的项目中有一个源文件,它具有几个对性能极为敏感的功能(每秒被称为百万次)。实际上,先前的维护者决定编写一个函数的12个副本,每个副本的差别都很小,以节省在单个函数中检查条件的时间。 不幸的是,这意味着代码是要维护的PITA。我想删除所有重复的代码,只写一个模板。但是,Java语言不支持模板,我不确定泛型是否适合于此。 我目前的计划是写一个文件,该文件生成该函数的12个副本(实际上是一个只能使用的模板扩展器)。对于为什么必须以编程方式生成文件,我当然会提供很多解释。 我担心的是,这将导致将来的维护人员感到困惑,并且如果他们在修改文件后忘记重新生成文件,或者(如果更糟糕的话)他们以编程方式生成的文件进行修改,则可能会引入讨厌的错误。不幸的是,除了没有用C ++重写整个过程外,我看不到任何解决方法。 这种方法的好处是否大于缺点?我应该改为: 发挥性能优势,并使用单个可维护的功能。 添加有关为何必须重复执行该功能12次的说明,并应承担维护负担。 尝试将泛型用作模板(它们可能无法那样工作)。 大吼大叫的老维护者,使代码的性能取决于单个函数。 其他保持性能和可维护性的方法? PS:由于该项目的设计不佳,对功能进行性能分析非常棘手……但是,这位前维护人员说服了我,性能下降是不可接受的。我认为他的意思是超过5%,尽管这完全是我的猜测。 也许我应该详细说明一下。这12份副本执行的任务非常相似,但差别很小。在整个函数中的不同地方存在差异,因此不幸的是,有很多很多条件语句。有效地有6种“操作模式”和2种“范例”(由我自己编造的词)。要使用该功能,可以指定操作的“模式”和“范例”。这从来都不是动态的。每段代码仅使用一种模式和范例。所有12个模式范例对都在应用程序中的某个位置使用。这些函数恰当地命名为func1到func12,偶数代表第二个范例,奇数代表第一个范例。 我知道,如果以可维护性为目标,那将是最糟糕的设计。但是它似乎“足够快”,并且这段代码已经有一段时间不需要任何更改了。也值得注意的是原始功能尚未删除(尽管据我所知这是无效代码) ,因此重构将很简单。

3
动态语言有真正的优势吗?[关闭]
首先,我想说Java是我曾经使用过的唯一语言,所以请原谅我对此主题的无知。 动态类型的语言允许您将任何值放在任何变量中。因此,例如,您可以编写以下函数(伪代码): void makeItBark(dog){ dog.bark(); } 您可以在其中传递任何值。只要该值具有bark()方法,代码就会运行。否则,将引发运行时异常或类似情况。(如果我对此有误,请纠正我)。 貌似,这为您提供了灵活性。 但是,我阅读了一些有关动态语言的文章,人们说的是,在以动态语言设计或编写代码时,您会考虑类型并将其考虑在内,就像使用静态类型语言一样。 因此,例如,在编写makeItBark()函数时,您打算让它只接受“可能吠叫的东西”,而您仍然需要确保仅将这些东西传递给它。唯一的区别是,当您犯错时,编译器现在不会告诉您。 当然,此方法有一个优点,那就是在静态语言中,要实现“此函数接受任何可能吠叫的东西”,您需要实现一个显式Barker接口。不过,这似乎是次要的优势。 我想念什么吗?通过使用动态类型的语言,我实际上可以获得什么?

7
使用异常作为工具尽早“捕获”错误是否可以?
我使用异常来尽早发现问题。例如: public int getAverageAge(Person p1, Person p2){ if(p1 == null || p2 == null) throw new IllegalArgumentException("One or more of input persons is null"). return (p1.getAge() + p2.getAge()) / 2; } 我的程序永远不要传递null此函数。我从来没有打算。但是,众所周知,编程中会发生意想不到的事情。 如果发生此问题,将引发异常,以便在导致程序其他位置出现更多问题之前,找出并修复该异常。异常会停止程序,并告诉我“这里发生了坏事,请修复它”。而不是null在程序周围四处走动,从而导致其他地方出现问题。 现在,您是对的,在这种情况下,这null将立即导致NullPointerException立马,所以它可能不是最佳示例。 但以这种方法为例: public void registerPerson(Person person){ persons.add(person); notifyRegisterObservers(person); // sends the person object to all kinds of …

6
了解“编程接口”
我遇到过很多术语“编程为接口而不是实现”,我想我有点理解它的意思。但是我想确保我了解它的好处以及可能的实现。 “对接口进行编程”意味着,在可能的情况下,应该引用一个类的更抽象级别(一个接口,抽象类,有时甚至是某种超类),而不是引用一个具体的实现。 Java中的一个常见示例是使用: List myList = new ArrayList();代替ArrayList myList = new ArrayList();。 我对此有两个问题: 我想确保我了解这种方法的主要好处。我认为好处主要是灵活性。将对象声明为更高级的引用,而不是具体的实现,可以在整个开发周期和整个代码中提供更大的灵活性和可维护性。它是否正确?灵活性是主要好处吗? 还有更多的“编程接口”方法吗?还是“将变量声明为接口而不是具体的实现”是此概念的唯一实现? 我不是在谈论Java构造接口。我说的是OO原则:“编程为接口,而不是实现”。按照这个原理,世界“接口”是指一个类的任何“超类型” -接口,抽象类或简单的超类,它比更具体的子类更抽象,更不具体。

5
C ++样式指南[关闭]
现在,我在C ++代码中使用了Google C ++样式指南,对此我感到非常满意。 最近有人告诉我,该指南非常糟糕:Google内部使用(我知道),该指南已经过时,并且推广了一些非常糟糕的做法。所以我想使用另一种编码风格。 有哪些良好且使用合理的C ++样式指南?我为gcc和Visual Studio编写代码,并且使用了许多C ++ 11功能。 我最喜欢Google C ++样式指南的是缩进,空格和命名约定(特别是所有类,类型(包括typedef,类型别名和模板别名)都以大写的首字母命名)。 我知道任何答案都是主观的(希望在此站点上可以),并且希望您提出任何意见,但我对最近使用的指南很感兴趣。

5
Javascript,HTML和CSS之间的紧密耦合:更现代的方法?
看到Java绑定到某些选择器以查找元素,存储数据和侦听事件是很常见的。看到这些用于样式的选择器也是很常见的。 jQuery(及其选择器引擎Sizzle)通过使用CSS类型的语法引用元素来支持和促进这一点。因此,在构建项目时,这种技术特别难以“取消学习”(或重构)。 我已经了解到,这是HTML和Javascript开发历史的结果,并且已经建立了浏览器来有效使用/解析/呈现这种耦合。但是随着网站变得越来越复杂,这种现实会给组织和维护这些单独的层带来困难。 我的问题是:现代网站是否可以避免这种情况? 如果我是前端开发的新手,并且希望以“正确的方式”学习事物,那么值得一开始学习去耦和避免这种依赖吗?这是否意味着避免使用jQuery,而推荐使用可促进更解耦结构的库?
29 javascript  html  css  jquery 

2
为什么Unix链接程序称为“ ld”
试图在网上搜索,但找不到答案。它可能与“负载”有关,但这对我来说没有多大意义。 显然,“ ln”已经被使用,但是“ d”从何而来?
29 history 

10
应该将临时代码置于版本控制之下,如何进行?
这是临时/本地代码的一些示例。为了使用代码库,它是必需的,但是成为其中的一部分将是有害的: 项目文件。可能需要编辑路径才能反映当前PC上的布局。 生成文件。例如,在调试过程中可能需要关闭优化,但对于CI服务器则不需要。 肮脏的丑陋骇客。例如return 7在一个函数的中间,为了测试某些东西(取决于该函数),并怀疑它的值是7。我分行的生活 我尝试将它们保持在git commit中,在将其推送到存储库然后推送之前,我总是将其重新定位到顶部HEAD~。这非常不便,不适用于svn。藏起来让我更加恐惧-“我记得推后弹开吗?”。 每次汇编汇编提交时,使代码脱离版本控制都会带来令人不快的噪音,而且它可能在某个星期五晚上偶然被引入到提交中。 对于这样的一次性代码,什么是理智的解决方案?

3
为什么C ++中的布尔类型支持++但不支持-?
为什么--布尔没有运算符,而布尔运算符却存在++呢? 我用C ++尝试过,不知道我的问题是否适用于另一种语言。我也很高兴知道。 我知道,我可以将运算符++与bool一起使用。它使布尔值等于true。 bool b = false; b++; // Now b == true. 为什么我们不能--相反地使用运算符? bool b = true; b--; // Now b == false; 它不是很有用,但我很好奇。

1
如何以敏捷开发人员的身份编写“ SMART”目标?
与许多公司一样,我工作的公司正在过渡到基于SMART目标的绩效评估系统。我的团队是一个高效的敏捷开发团队,采用了Extreme Programming的实践。为了使我们受益匪浅,我们在敏捷实践中的使用得到了直接和高层管理人员的全面支持。 为了完成工作,我们的团队利用了三周的迭代时间。除了立即迭代之外,我们还制定了一个总体计划。这意味着我们从现在开始的几个季度将要完成的工作比我们在最近一个季度将要完成的工作要模糊得多。我们当然对项目的发展方向有一个大致的了解,但是这里的关键字是general。 考虑到我们对团队中项目规划人员的态度,包括我自己在内,发现很难写出具体,可测量,可实现,相关且有时限的目标(SMART)。 关于SoftwareEngineering.se的两个现有问题很好地解决了我们的一些担忧: 对程序员来说,一个好的SMART目标的例子是什么? SMART目标对程序员有用吗? 但是,在敏捷开发团队中工作时,这些问题在处理SMART目标方面引起了比具体问题更多的一般回答。作为敏捷开发人员,您如何编写五到七个长达一年的目标,这些目标是特定的,可测量的,可实现的,相关的且有时间限制的?

1
Inglish解析器(适用于《霍比特人》 1982年)
着迷于阅读有关文本冒险游戏《霍比特人》的内容,该游戏的功能强大的解析器名为“ Inglish”: ... Inglish允许输入一些高级句子,例如“向Gandalf询问好奇的地图,然后拿剑并杀死巨魔”。解析器复杂而直观,引入了代词,副词(“恶意攻击地精”),标点符号和介词,并允许玩家以以前无法实现的方式与游戏世界互动。 我想知道是否有人知道Inglish解析器引擎以及开发它的程序员的历史和/或遗产。

8
代码和数据的分离如何成为一种惯例?
请仔细阅读问题:它询问的是方式,而不是原因。 我最近遇到了这个答案,它建议使用数据库存储不可变数据: 听起来您描述的许多魔术数字(尤其是如果它们是部分依赖的)实际上是数据,而不是代码。[...]它可能意味着一个SQL类型的数据库,或者可能只是意味着一个格式化的文本文件。 在我看来,如果您的数据属于程序的一部分,那么要做的就是将其放入程序中。例如,如果您程序的功能是计算元音,那么里面有什么问题vowels = "aeiou"呢?毕竟,大多数语言都具有专门为此目的设计的数据结构。您为什么要麻烦将数据放入“格式化的文本文件”中来分离数据,如上所述?为什么不只使用您选择的编程语言来格式化该文本文件?现在是数据库吗?还是代码? 我敢肯定,有些人会认为这是一个愚蠢的问题,但我会严肃地问这个问题。我觉得“分开的代码和数据”在文化上正在逐渐成为一种不言而喻的真理,以及诸如“不要给变量带来误导性的名称”和“不要仅因为您的语言考虑而使用空格”之类的显而易见的事情。无关紧要”。 例如,这篇文章:从P代码中分离数据的问题。有问题吗?什么问题?如果Puppet是用于描述我的基础结构的语言,为什么它不能还描述名称服务器是8.8.8.8?在我看来,问题不在于代码和数据混杂在一起,1而是Puppet缺乏足够丰富的数据结构和与其他事物交互的方式。 我发现这种转变令人不安。面向对象的编程说“我们想要任意丰富的数据结构”,因此赋予数据结构以代码的能力。结果就是封装和抽象。甚至SQL数据库都有存储过程。当您将数据隔离到YAML或文本文件或哑数据库中时,就好像要从代码中删除肿瘤一样,所有这些都将丢失。 谁能解释这种将数据与代码分离的做法是如何发生的以及它的发展方向?谁能引用知名人士的出版物,或者提供一些相关的数据,作为“新兴的诫命”来说明“从数据中分离代码”,并说明其起源? 1:甚至可以做出这样的区分。Lisp程序员,我在看着你。

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.