Hardcoding is something that should be avoided as much as possible.
If you hardcode something on your code it will completely "destroy" the portability of your code in a great extent. Even with a platform independant languages you will not able to say "Compile once, Run anywhere". Since it is not a good software engineering practice, I think avoiding hardcodes is better.
But I know in some cases we need that, specially in debugging the codes. The way I suggest is: First develop the code with hard codes, make it stable and eliminate the hardcodes then...
And there might be some cases that we need hardcoding, due to security concerns etc :). you might not be allowed to use registry, configuration files, any thing because they can increase the attack surface. But I think it is a rare case.
Nothing wrong with hardcoding provided its done right for the right reasons!
"Doing it right" means concentrating all your hard coding in one or two modules.
For C define all the values in a codes.h for Java have a codes.java class which is just full of public constants.
There are several "right reasons" for hard coding.
simplicity.
support - if your values are in an external configuration file you cannot protect yourself against stupid configurations and you cannot test all possible configurations, if its hard coded then you know what you are dealing with.
Performance.
readability. You can see everything you need to know in your edit session!
There are also several reasons to avoid over complex configuration files. If you have enough parameters and options you just end up programing in a not very good language.
But in praxis I tend to hard code some values. The main reasons to hard-code are:
By specification there should be exactly this value, it shouldn't be changed. Making it changeable could make the software unstable.
The value could probably be changed later, but it is not know by whom and how, so you don't know where it belongs. It could belong to the config file, the resource files, the database, the registry or somewhere else. Putting it on the wrong place is worse than hard coding it.
There are some "hard-coding best praxis's" I think are never over-engineering:
Hard coded values should always be declared on a central places in constants.
Even if a value is hard-coded, it should still be passed as an argument to components, that don't have to care where the value comes form. It makes your component reusable.
This makes it possible to move the hard-coded values to an other place later.
As someone who's had some experience with hard-coding in my early days (don't tell anybody mate), I can confidently tell you that it will come back to haunt you. There's this application that I made (which I don't talk about now) which had to be completely re-written cause it had a lot of hard-coded content. That was back in 1998 mate.
Don't do it unless you don't want to support that client in the future. The time you save now, will be time spent in fixing later.
I think hard coding the default values is the way to go for everything that might be needed to be configurable:
In our GUI code (client-server) we use a three step lookup: we ask our preferences instance for a preference with a default value. But this passed default value is overridden by a config file, if it exists.
That way we have two options later. If a customer wants something different, we can change it in the config file. And we can also configure our settings dialog to make it user configurable.
So effectively we have hard codes, that can be overridden by config, that can be overridden by user preferences.
The only problem is to document all the preferences keys...
Usually more time and money is spent maintaining the code than writing it originally. 80% of total spent on the code is typically spent during the maintenance period. Therefore anything that makes maintenance harder will eventually cost more than doing it right the first time. Hard-coding is definitely one thing that makes maintenance harder, and consequently is a bad idea.
But as Anthony mentioned, I put the configurable values in their own class. This way they are configurable at compile time, but without the added complexities that come with having an external xml/txt file for configuration.
I only use xml/txt files for configuration where absolutely necessary. Otherwise you're just over-engineering which can be just as bad, if not worse than hard coding. Not to mention there's a lot of stuff people put in configuration files which you don't want the client to change at all.
If you need different configurations for different clients, no problem, put the hard coded values in their own assembly/dll and deploy different configuration assemblies per client.
If I need a char * to point to 12 characters, I can safely write malloc(12) because sizeof(char) will always be 1. If I need an int * to point to 12 integers, I write malloc(12 * sizeof(int)).
Hardcode the few things that will absolutely, positivelynever change. For everything else, it takes an extra two seconds, so why not go ahead and do it?
I generally try and put values into a configuration file rather than hard-code. If a value must be hard-coded, I create a constant with the hard-coded value and everywhere in the code references the same constant. If the value needs to change it can be done in one place.
For application-wide constants, I normally create a class and create constants in that.
There're a several factors involved that is hardly to make an assertion that will cover all cases.
If it is a long project with several cycles then if you start hard coding it is likely that they will rather soon than later will popup again. So in these cases is better to fix with a proper solution.
But if you have a project with a short cycle, or with predefined schedule and you have to ship the product anyway, most clients will be satisfied if the product work, they will not care about the internals. But in these cases I prefer to hard code a solution, but let the path open so in the future it will be easy to make a proper solution.
Hard coding is bad anyway, but I you document properly it can make the life of the next person much easier, and will probably not curse you, at least not much ;) .
But from my experience I started avoiding to hard code from the go, and only using them when I've no other option, and always documenting those cases so later I can fix it properly when I've time.
That's almost like saying, "I like to write my code without comments because it takes less time to get what I wanted."
Of course, that's not to say that hard coding is always a Very Bad Thing. (I mean, it'd be kind of stupid to store, say, a mathematical constant such as π, e, or Planck's constant in a config file. Also, hard coding a lookup table for, say, sine/cosine values would probably be a lot more efficient than loading it from a file.) But hard coding data purely for the sake of convenience is not a smart idea. It's inflexible and makes modifying data later on much more troublesome than it has to be.
Also, hard coding can make localization extremely difficult, if not impossible in many situations. If it's an internal app for some company, then I guess it doesn't really matter to some extent, but that doesn't make it a good software development practice in general.
If hard-coding is done correctly, it can be a bonus. For example, if you hard coded your array sizes instead of doing dynamic allocation, it makes it easy for debugging since you know exactly where the array resides in memory. This is assuming that you actually want to know things like these though.
I always create a constant, but close as possible/sensible to where its "only" use is to be.
If I then need it somewhere else in the unit, it gets moved to the top of the unit.
If its then needed in another unit, the constant gets moved to a settings unit.
If someone wants it changable it gets moved to the settings unit (if not already), and set from a config file etc.
At the end of the day the name you give the thing is its documentation, at the very least it means you don't get your 73 mixed up with someone elses 73. If you see what I mean.
Regarding hard coded strings in C/C++; I usually #define them as the simplest way to avoid hard coding (though in a sense that is still of hard coded). The reason is that a defined identifier that is misspelled will be caught by the compiler, whereas anything between quotation marks will not.
My attitude to configuration? It's too often done poorly and too casually - increasing TCO as users try to grok 100s of configurable values. Add configurability (soft coding) only when proven necessary.
When it's necessary ... A configurable value ought to be treated with the same mistrust as user input, and provide lucid error messages when input is bad. Most components should be isolated from the configuration infrastructure - just as you isolate most components from any data access infrastructure. Once isolated from the configuration infrastructure, you can and should test how the component handles various "input" from the configuration system. Most important, the program should work just fine with an absolute minimum of configuration.
However, this type of anti-pattern is extremely common:
Or this (would you ever put user input directly into an href? I wouldn't. Somehow, many people trust configuration values far too much ).
LinkWriter.href=configuration["supportUrl"]
When to configure? As you prove you need to. Good separation of concerns will make it easy to make a value configurable at a later point. I'd drop responsibility for locating a file into a file locater.
Somewhere behind my file locator I might or might not refer to a configuration file, a database. I'll probably start hard coding to a "images" directory in the application directory. Configuration comes when we have a use case for flexibility (someone wants to put it on SAN?) but not before. Anyway, most of the app should not whether it's configured or not. I'd likely use some dependency injection on the file locater to verify that it correctly handled lousy input from the configuration file.
Also: Configuration is almost always loosely typed, not compiled, and thus much more dangerous than code. This risk is rarely respected by developers (but heavily respected by sysadmins). I've debated using a script language like python / ironpython / boo for configuration needs. I'd get the ability to change stuff after compilation, with a much more free syntax and type checking than xml or text.
Caveats: My attitude assumes an iterative release cycle. If you have a 2-10 year release cycle, like Microsoft, you'll want to bias in favor of configuring many more values .
发布评论
评论(17)
如果您在代码中硬编码某些内容,它将彻底“破坏”代码的可移植性程度。 即使使用独立于平台的语言,您也不能说“编译一次,随处运行”。 由于这不是一个好的软件工程实践,我认为避免硬编码更好。
但我知道在某些情况下我们需要它,特别是在调试代码时。 我建议的方法是:首先使用硬代码开发代码,使其稳定并消除硬代码,然后......
并且由于安全问题等原因,在某些情况下我们可能需要硬编码:)。 您可能不被允许使用注册表、配置文件等任何东西,因为它们会增加攻击面。 但我认为这种情况很少见。
If you hardcode something on your code it will completely "destroy" the portability of your code in a great extent. Even with a platform independant languages you will not able to say "Compile once, Run anywhere". Since it is not a good software engineering practice, I think avoiding hardcodes is better.
But I know in some cases we need that, specially in debugging the codes. The way I suggest is: First develop the code with hard codes, make it stable and eliminate the hardcodes then...
And there might be some cases that we need hardcoding, due to security concerns etc :). you might not be allowed to use registry, configuration files, any thing because they can increase the attack surface. But I think it is a rare case.
IT 领域不存在灵丹妙药。
如果有人告诉你做蠢事,保存电子邮件线程并保存你的工作
Silver bullets do not exist in IT.
If someone tell you to do the dumb thing, save the email thread and save your J.O.B.
硬编码没有任何问题,只要它出于正确的原因而正确完成!
“正确行事”意味着将所有硬编码集中在一两个模块中。
对于C,定义codes.h中的所有值;对于Java,有一个codes.java类,其中充满了公共常量。
硬编码有几个“正确的理由”。
还有几个原因需要避免过于复杂的配置文件。 如果您有足够的参数和选项,您最终只会使用一种不太好的语言进行编程。
Nothing wrong with hardcoding provided its done right for the right reasons!
"Doing it right" means concentrating all your hard coding in one or two modules.
For C define all the values in a codes.h for Java have a codes.java class which is just full of public constants.
There are several "right reasons" for hard coding.
There are also several reasons to avoid over complex configuration files. If you have enough parameters and options you just end up programing in a not very good language.
从概念上讲,我不喜欢太多的硬编码。
但在实践中,我倾向于对一些值进行硬编码。 硬编码的主要原因是:
有一些“硬编码最佳实践”我认为永远不要过度设计:
这使得以后可以将硬编码值移动到其他位置。
Conceptually I don't like too much hard-coding.
But in praxis I tend to hard code some values. The main reasons to hard-code are:
There are some "hard-coding best praxis's" I think are never over-engineering:
This makes it possible to move the hard-coded values to an other place later.
作为一个在我早期有过硬编码经验的人(不要告诉任何人),我可以自信地告诉你,它会回来困扰你。 我制作了这个应用程序(我现在不谈论它),它必须完全重写,因为它有很多硬编码内容。 那是1998年的事了,伙计。
除非您将来不想支持该客户,否则不要这样做。 您现在节省的时间将用于以后修复。
As someone who's had some experience with hard-coding in my early days (don't tell anybody mate), I can confidently tell you that it will come back to haunt you. There's this application that I made (which I don't talk about now) which had to be completely re-written cause it had a lot of hard-coded content. That was back in 1998 mate.
Don't do it unless you don't want to support that client in the future. The time you save now, will be time spent in fixing later.
在嵌入式和关键软件中,硬编码有两个主要优点:
这意味着更少的CPU负载,即更少的功耗,更少或没有动态内存分配,更少的算法复杂性,即更容易调试,...
通常,硬编码编码数据放在单个头文件中以提高可维护性。
此外,从数据库自动生成该头文件提供了灵活性。
In embedded and critical software, hardcoding has two main advantages:
This means less CPU load, i.e. less power consumption, less or no dynamic memory allocation, less algorithmic complexity, i.e. easier debugging, ...
Usually, hard coded data are put in a single header file for more maintainability.
Moreover, flexibility is provided by an automatic generation of this header file from a database.
我认为对默认值进行硬编码是实现可能需要配置的所有内容的方法:
在我们的 GUI 代码(客户端-服务器)中,我们使用三步查找:我们向首选项实例询问具有默认值的首选项。 但是传递的默认值将被配置文件(如果存在)覆盖。
这样我们以后就有两个选择。 如果客户想要不同的东西,我们可以在配置文件中更改它。 我们还可以配置我们的设置对话框,使其成为用户可配置的。
因此,我们实际上拥有硬代码,可以通过配置覆盖,可以通过用户首选项覆盖。
唯一的问题是记录所有首选项键......
I think hard coding the default values is the way to go for everything that might be needed to be configurable:
In our GUI code (client-server) we use a three step lookup: we ask our preferences instance for a preference with a default value. But this passed default value is overridden by a config file, if it exists.
That way we have two options later. If a customer wants something different, we can change it in the config file. And we can also configure our settings dialog to make it user configurable.
So effectively we have hard codes, that can be overridden by config, that can be overridden by user preferences.
The only problem is to document all the preferences keys...
通常,维护代码所花费的时间和金钱比最初编写代码所花费的时间和金钱要多。 代码总花费的 80% 通常花费在维护期间。 因此,任何使维护变得更加困难的事情最终都会比第一次就做好的成本更高。 硬编码肯定会让维护变得更加困难,因此是一个坏主意。
Usually more time and money is spent maintaining the code than writing it originally. 80% of total spent on the code is typically spent during the maintenance period. Therefore anything that makes maintenance harder will eventually cost more than doing it right the first time. Hard-coding is definitely one thing that makes maintenance harder, and consequently is a bad idea.
硬编码是必经之路!
但正如安东尼提到的,我将可配置的值放在它们自己的类中。 这样,它们就可以在编译时进行配置,但不会因为使用外部 xml/txt 文件进行配置而增加复杂性。
我只在绝对必要的情况下使用 xml/txt 文件进行配置。 否则,你只是过度设计,这可能和硬编码一样糟糕,甚至更糟糕。 更不用说人们在配置文件中放入了很多您根本不希望客户端更改的内容。
如果您需要为不同的客户端提供不同的配置,没问题,将硬编码值放入它们自己的程序集/dll 中,并为每个客户端部署不同的配置程序集。
正如 Ayende 所说,硬编码一切是实现变革的关键。
Hard coding is the way to go!
But as Anthony mentioned, I put the configurable values in their own class. This way they are configurable at compile time, but without the added complexities that come with having an external xml/txt file for configuration.
I only use xml/txt files for configuration where absolutely necessary. Otherwise you're just over-engineering which can be just as bad, if not worse than hard coding. Not to mention there's a lot of stuff people put in configuration files which you don't want the client to change at all.
If you need different configurations for different clients, no problem, put the hard coded values in their own assembly/dll and deploy different configuration assemblies per client.
As Ayende says, hard coding everything is the key to enabling change.
如果我需要
char *
指向 12 个字符,我可以安全地编写malloc(12)
因为sizeof(char)
将始终为 1如果我需要一个int *
来指向12个整数,我会写malloc(12 * sizeof(int))
。对一些绝对、积极永远不会改变的事情进行硬编码。 对于其他事情,都需要额外的两秒钟,所以为什么不继续做呢?
If I need a
char *
to point to 12 characters, I can safely writemalloc(12)
becausesizeof(char)
will always be 1. If I need anint *
to point to 12 integers, I writemalloc(12 * sizeof(int))
.Hardcode the few things that will absolutely, positively never change. For everything else, it takes an extra two seconds, so why not go ahead and do it?
我通常尝试将值放入配置文件中,而不是硬编码。 如果必须对值进行硬编码,我会使用硬编码值创建一个常量,并且代码中的所有位置都引用相同的常量。 如果需要更改该值,可以在一处完成。
对于应用程序范围的常量,我通常创建一个类并在其中创建常量。
I generally try and put values into a configuration file rather than hard-code. If a value must be hard-coded, I create a constant with the hard-coded value and everywhere in the code references the same constant. If the value needs to change it can be done in one place.
For application-wide constants, I normally create a class and create constants in that.
这涉及到几个因素,很难做出涵盖所有情况的断言。
如果这是一个有多个周期的长项目,那么如果您开始硬编码,它们很可能很快就会再次弹出。 因此,在这些情况下,最好使用适当的解决方案进行修复。
但是,如果您的项目周期短,或者有预定义的时间表,并且您无论如何都必须交付产品,那么如果产品有效,大多数客户都会感到满意,他们不会关心内部结构。 但在这些情况下,我更喜欢硬编码解决方案,但让路径开放,这样将来就可以轻松制定正确的解决方案。
硬编码无论如何都是不好的,但是我正确地记录它可以使下一个人的生活变得更轻松,并且可能不会诅咒你,至少不会太多;)。
但根据我的经验,我开始避免立即进行硬编码,并且仅在没有其他选择时才使用它们,并且始终记录这些情况,以便稍后我可以在有时间时正确修复它。
There're a several factors involved that is hardly to make an assertion that will cover all cases.
If it is a long project with several cycles then if you start hard coding it is likely that they will rather soon than later will popup again. So in these cases is better to fix with a proper solution.
But if you have a project with a short cycle, or with predefined schedule and you have to ship the product anyway, most clients will be satisfied if the product work, they will not care about the internals. But in these cases I prefer to hard code a solution, but let the path open so in the future it will be easy to make a proper solution.
Hard coding is bad anyway, but I you document properly it can make the life of the next person much easier, and will probably not curse you, at least not much ;) .
But from my experience I started avoiding to hard code from the go, and only using them when I've no other option, and always documenting those cases so later I can fix it properly when I've time.
这几乎就像在说:“我喜欢编写不带注释的代码,因为这样可以花费更少的时间来获得我想要的东西。”
当然,这并不是说硬编码总是是一件非常糟糕的事情。 (我的意思是,在配置文件中存储数学常数(例如 π、e 或普朗克常数)有点愚蠢。此外,对正弦/余弦值的查找表进行硬编码可能会比从文件加载要高效得多。)但是纯粹为了方便而对数据进行硬编码并不是一个明智的想法。 它不灵活,并且使以后修改数据变得比原来要麻烦得多。
此外,在许多情况下,硬编码即使不是不可能,也会使本地化变得极其困难。 如果它是某个公司的内部应用程序,那么我想在某种程度上它并不重要,但这并不能使其成为一种良好的软件开发实践。
That's almost like saying, "I like to write my code without comments because it takes less time to get what I wanted."
Of course, that's not to say that hard coding is always a Very Bad Thing. (I mean, it'd be kind of stupid to store, say, a mathematical constant such as π, e, or Planck's constant in a config file. Also, hard coding a lookup table for, say, sine/cosine values would probably be a lot more efficient than loading it from a file.) But hard coding data purely for the sake of convenience is not a smart idea. It's inflexible and makes modifying data later on much more troublesome than it has to be.
Also, hard coding can make localization extremely difficult, if not impossible in many situations. If it's an internal app for some company, then I guess it doesn't really matter to some extent, but that doesn't make it a good software development practice in general.
如果硬编码正确完成,这可能是一个额外的好处。 例如,如果您对数组大小进行硬编码而不是进行动态分配,则可以轻松进行调试,因为您确切地知道数组在内存中的位置。 这是假设您确实想了解这些事情。
If hard-coding is done correctly, it can be a bonus. For example, if you hard coded your array sizes instead of doing dynamic allocation, it makes it easy for debugging since you know exactly where the array resides in memory. This is assuming that you actually want to know things like these though.
我总是创建一个常量,但尽可能接近/合理地接近它的“唯一”用途。
如果我需要在设备中的其他地方使用它,它就会被移到设备的顶部。
如果另一个单元需要它,则该常数将被移动到设置单元。
如果有人想要更改它,它会被移动到设置单元(如果还没有),并从配置文件等进行设置。
归根结底,您给该东西的名称就是它的文档,至少这意味着您不这样做不要把你的 73 与别人的 73 混淆。如果你明白我的意思。
I always create a constant, but close as possible/sensible to where its "only" use is to be.
If I then need it somewhere else in the unit, it gets moved to the top of the unit.
If its then needed in another unit, the constant gets moved to a settings unit.
If someone wants it changable it gets moved to the settings unit (if not already), and set from a config file etc.
At the end of the day the name you give the thing is its documentation, at the very least it means you don't get your 73 mixed up with someone elses 73. If you see what I mean.
关于C/C++中的硬编码字符串; 我通常将它们定义为避免硬编码的最简单方法(尽管从某种意义上说,这仍然是硬编码)。 原因是编译器会捕获拼写错误的已定义标识符,而引号之间的任何内容都不会。
Regarding hard coded strings in C/C++; I usually #define them as the simplest way to avoid hard coding (though in a sense that is still of hard coded). The reason is that a defined identifier that is misspelled will be caught by the compiler, whereas anything between quotation marks will not.
我对配置的态度? 它常常做得很糟糕而且太随意——当用户尝试获取数百个可配置值时,TCO 就会增加。 仅在证明有必要时才添加可配置性(软编码)。
当有必要时......可配置的值应该像用户输入一样受到不信任的对待,并在输入错误时提供清晰的错误消息。 大多数组件应该与配置基础设施隔离——就像将大多数组件与任何数据访问基础设施隔离一样。 一旦与配置基础设施隔离,您可以而且应该测试该组件如何处理来自配置系统的各种“输入”。 最重要的是,该程序应该可以在绝对最少的配置下正常工作。
然而,这种类型的反模式非常常见:
或者这个(你会把用户输入直接放入 href 中吗?我不会。不知何故,许多人过于信任配置值)。
什么时候配置? 当你证明你需要的时候。 良好的关注点分离将使稍后可以轻松配置值。 我会放弃将文件定位到文件定位器中的责任。
在我的文件定位器后面的某个地方,我可能会或可能不会引用配置文件、数据库。 我可能会开始对应用程序目录中的“images”目录进行硬编码。 当我们有一个灵活性用例(有人想将其放在 SAN 上?)时,就会进行配置,但在此之前不会。 不管怎样,大多数应用程序都不应该,无论它是否配置。 我可能会在文件定位器上使用一些依赖项注入来验证它是否正确处理了来自配置文件的糟糕输入。
另外:配置几乎总是松散类型的,未编译的,因此比代码危险得多。 这种风险很少受到开发人员的重视(但受到系统管理员的高度重视)。 我曾经讨论过使用 python / Ironpython / boo 这样的脚本语言来满足配置需求。 我能够在编译后更改内容,并使用比 xml 或文本更自由的语法和类型检查。
注意事项:我的态度假设有一个迭代的发布周期。 如果您有 2-10 年的发布周期(如 Microsoft),您将希望偏向于配置更多值。
My attitude to configuration? It's too often done poorly and too casually - increasing TCO as users try to grok 100s of configurable values. Add configurability (soft coding) only when proven necessary.
When it's necessary ... A configurable value ought to be treated with the same mistrust as user input, and provide lucid error messages when input is bad. Most components should be isolated from the configuration infrastructure - just as you isolate most components from any data access infrastructure. Once isolated from the configuration infrastructure, you can and should test how the component handles various "input" from the configuration system. Most important, the program should work just fine with an absolute minimum of configuration.
However, this type of anti-pattern is extremely common:
Or this (would you ever put user input directly into an href? I wouldn't. Somehow, many people trust configuration values far too much ).
When to configure? As you prove you need to. Good separation of concerns will make it easy to make a value configurable at a later point. I'd drop responsibility for locating a file into a file locater.
Somewhere behind my file locator I might or might not refer to a configuration file, a database. I'll probably start hard coding to a "images" directory in the application directory. Configuration comes when we have a use case for flexibility (someone wants to put it on SAN?) but not before. Anyway, most of the app should not whether it's configured or not. I'd likely use some dependency injection on the file locater to verify that it correctly handled lousy input from the configuration file.
Also: Configuration is almost always loosely typed, not compiled, and thus much more dangerous than code. This risk is rarely respected by developers (but heavily respected by sysadmins). I've debated using a script language like python / ironpython / boo for configuration needs. I'd get the ability to change stuff after compilation, with a much more free syntax and type checking than xml or text.
Caveats: My attitude assumes an iterative release cycle. If you have a 2-10 year release cycle, like Microsoft, you'll want to bias in favor of configuring many more values .