英文:
When to reuse functions?
问题
我在我的程序中有一个生成随机字符串的函数。
func randString(s []rune, l int) string
s
是一个包含字符串中可能字符的 rune 切片。我传入了一个包含大写和小写字母字符的 rune 切片。l
确定了字符串的长度。这个函数运行得很好。但是我还需要生成用于 HTML 颜色代码的随机十六进制字符串。
似乎所有的资料都说重用代码是良好的编程实践。所以我又创建了一个包含 [1-9a-f]
的 []rune
,并将其传递给 randString
函数。但后来我意识到标准库已经包含了适合我需求的整数类型的格式化动词。
实际上,是重用我的 randString
函数好呢,还是编写一个单独的(更高效的)函数好呢?我可以生成一个随机整数,然后使用 Sprintf 来格式化它,而不是像 randString
那样循环生成 6 个随机整数。
英文:
I have a function in my program that generates random strings.
func randString(s []rune, l int) string
s
is a slice of runes containing the possible characters in the string. I pass
in a rune slice of both capital and lowercase alphabetic characters. l
determines the length of the string. This works great. But I also need to
generate random hex strings for html color codes.
It seems all sources say that it's good programming practice to reuse code. So I
made another []rune
that held [1-9a-f]
and feed that into randString
. That
was before I realized that the stdlib already inclues formatting verbs for int
types that suit me perfectly.
In practice, is it better to reuse my randString
function or code a separate
(more efficient) function? I would generate a single random int and Sprintf it
rather than having to loop and generate 6 random ints which randString
does.
答案1
得分: 3
1)如果标准库中有一个精确的解决方案,你应该始终选择使用它。
原因如下:
- 标准库经过测试。所以它会按照它所说的(或者我们期望的)去执行。即使其中有一个错误,它也会被发现(由你或其他人),并且会在不需要你的工作/努力的情况下得到修复。
- 标准库是用 Go 语言的惯用方式编写的。即使它比你编写的解决方案多做了一点点工作,它很可能会更快。
- 标准库可能会随着时间的推移而改进。你的程序可能会因为在新的 Go 版本中改进了某个实现而变得更快,而无需你的任何努力。
- 解决方案已经被提供(这意味着它已经准备好了,不需要你的时间)。
- 标准库是众所周知的,所以你的代码将更容易被其他人和你自己理解。
- 如果你已经导入了该包(或者将来会导入),这意味着零或最小的开销,因为库是静态链接的,所以你需要的函数已经链接到你的程序(编译后的可执行二进制文件)中。
2)如果标准库提供了一个解决方案,但它是一个通用解决方案,适用于类似的问题,并且提供了比你所需更多的功能:
- 这意味着它很可能不是最优解决方案,因为它可能使用更多的内存和/或比你的解决方案更慢。
- 你需要决定是否愿意为了上述的好处而牺牲一点性能损失。这还取决于你需要如何以及多少次使用它(例如,如果只使用一次,那就无关紧要;如果在一个非常频繁调用的无限循环中使用,就需要仔细考虑)。
3)另一方面,如果标准库提供的解决方案并不是为了解决你的问题而设计的,你应该避免使用它...
- 即使当前的实现是可接受的,如果它是为其他目的而设计的,将来对它的改进可能会使你对它的使用完全无用,甚至可能破坏它。
- 更不用说它会让其他开发人员在阅读、改进或使用你的代码时感到困惑(包括你自己,在一定时间后)。
顺便提一下:这个问题正好是关于你正在尝试创建的函数的:如何在 Go 中生成固定长度的随机字符串? 我已经提供了多个非常高效的解决方案。
英文:
1) If there is an exact solution in the standard library, you should like always choose to use that.
Because:
- The standard library is tested. So it does what it says (or what we expect it to do). Even if there is a bug in it, it will be discovered (by you or by others) and will get fixed without your work/effort.
- The standard library is written as idiomatic Go. Chances are it's faster even if it does a little more than what you need compared to the solution you could write.
- The standard library is (or may) improve by time. Your program may get faster just because an implementation was improved in a new Go release without any effort from your part.
- The solution is presented (which means it's ready and requires no time from you).
- The standard library is well and widely known, so your code will be easier to understand by others and by you later on.
- If you're already imported the package (or will in the near future), this means zero or minimal overhead as libraries are statically linked, so the function you need is already linked to your program (to the compiled executable binary).
2) If there is a solution provided by the standard library but it is a general solution to similar problems and/or offers more than what you need:
- That means it's more likely not the optimal solution for you, as it may use more memory and/or work more slowly as your solution could be.
- You need to decide if you're willing to sacrifice that little performance loss for the gains listed above. This also depends how and how many times you need to use it (e.g. if it's a one-time, it shouldn't matter, if it's in an endless loop called very frequently, it should be examined carefully).
3) And at the other end: you should avoid using a solution provided by the standard library if it wasn't designed to solve your problem...
- If it just happens that its "side-effect" solves your problem: Even if the current implementation would be acceptable, if it was designed for something else, future improvements to it could render your usage of it completely useless or could even break it.
- Not to mention it would confuse other developers trying to read, improve or use your code (you included, after a certain amount of time).
As a side note: this question is exactly about the function you're trying to create: How to generate a random string of a fixed length in golang? I've presented mutiple very efficient solutions.
答案2
得分: 1
这是相当主观的,与Go语言无关,但我认为你不应该仅仅为了重用而重用代码。你重用的代码越多,你的应用程序的不同部分之间的依赖关系就越多,结果就变得更难以维护和修改。易于理解和修改的代码尤其重要,特别是在团队合作中。
对于你的特定示例,我会这样做。
如果在你的包/应用程序中只生成一次随机颜色,那么使用fmt.Sprintf("#%06x", rand.Intn(256*256*256))
是完全可以的(正如Dave C建议的那样)。
如果在多个地方生成随机颜色,我会创建一个名为func randColor() string
的函数并调用它。请注意,现在你可以根据需要优化randColor
的实现,而不需要改变其余的代码。例如,你可以最初使用randString
来实现randColor
,然后在以后切换到更高效的实现方式。
英文:
This is fairly subjective and not go-specific but I think you shouldn't reuse code just for the sake of reuse. The more code you reuse the more dependencies you create between different parts of your app and as result it becomes more difficult to maintain and modify. Easy to understand and modify code is much more important especially if you work in a team.
For your particular example I would do the following.
If a random color is generated only once in your package/application then using fmt.Sprintf("#%06x", rand.Intn(256*256*256))
is perfectly fine (as suggested by Dave C).
If random colors are generated in multiple places I would create function func randColor() string
and call it. Note that now you can optimize randColor
implementation however you like without changing the rest of the code. For example you could have implemented randColor
using randString
initially and then switched to a more efficient implementation later.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论