Why is every variable name so cryptic?

blov · · 590 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Every Golang I read online is cryptic as fuck, as if some minified version was shared. I just wrote my first small go app, and looking for a project my brain hurts when every single variable name is a single character, how do I ever convey meaning from those names being unfamiliar with the code (and as if now, the syntax)?</p> <hr/>**评论:**<br/><br/>jeffrallen: <pre><p>It would help to give us examples to comment on. Absent those, let me propose we use Effective Go&#39;s code as an example. In it, the authors make the case for small variable names. In idiomatic Go, public names (types, methods) should be neither small nor stuttering. So zip.NewReader, not zip.CreateNewZipfileReader and not zip.NwRdr. In a local context, single letter variables are preferred.</p> <p>But not by you. ☺</p> <p>Jeff</p></pre>Graftak9000: <pre><p>Code like stated below is not extraordinary. Your zip.newReader is the most lengthy go I’ve seen so far. I’m all for getting with the program, using conventions of an environment, but this one actually makes it hard for me to get into go at all, which is unfortunate (for me).</p> <blockquote> <p>func (b *Writer) flush() error {<br/> if b.err != nil {<br/> return b.err<br/> }<br/> if b.n == 0 {<br/> return nil<br/> }<br/> n, err := b.wr.Write(b.buf[0:b.n])<br/> if n &lt; b.n &amp;&amp; err == nil {<br/> err = io.ErrShortWrite<br/> }<br/> if err != nil {<br/> if n &gt; 0 &amp;&amp; n &lt; b.n {<br/> copy(b.buf[0:b.n-n], b.buf[n:b.n])<br/> }<br/> b.n -= n<br/> b.err = err<br/> return err<br/> }<br/> b.n = 0<br/> return nil<br/> } </p> </blockquote></pre>tdewolff: <pre><p>I&#39;ve had a professor that taught me to never use <code>i</code> for indices in <code>for</code> loops, I get his point though that clarity is more important than brevity. But I think in this case the two are aligned. Using conventional variable names makes it more understandable, at least so for me. Just like <code>i</code> is an index in almost all code, so is <code>n</code> a size and <code>err</code> an error. Furthermore in Go you often see <code>r</code> as a reader, <code>w</code> a writer, <code>b</code> a buffer and <code>s</code> a string, etc.</p> <p>I don&#39;t know why you&#39;re so distracted by the short variable names, but perhaps take the time to get acquainted with the notation will ease things. Anyways, I&#39;d say <code>b.wr.Write</code> should&#39;ve been <code>b.w.Write</code> ;-)</p></pre>1Gijs: <pre><p>&#39;b.wr.Write should&#39;ve been b.w.Write&#39;</p> <p>Exactly where I stumbled as well ;-)</p></pre>Graftak9000: <pre><p>I&#39;ve read some online and I see now there&#39;s a train of thought supporting this idiom which made everything a bit more clear. It will remain a strong factor for me to get used to though, but if this is my most prominent issue, it&#39;s not all that bad.</p></pre>weberc2: <pre><p>If you think this is bad, you should try C. :p :)</p></pre>climbinglepton: <pre><p>I think that is plenty readable. Those are also unexported fields; it is really up to the author&#39;s discretion at that point. If you want to have longer names in your unexported code go ahead. The alternative there would be what? <code>b.bytesToWrite</code> instead of <code>b.n</code>? <code>bytesWritten</code> instead of <code>n</code>? Does that really help that much? <code>b.writer</code> instead of <code>b.wr</code>?</p> <p>I don&#39;t see why you&#39;r so up in arms about this or why you think this is a Go specific thing. Have you ever seen C code? I see this plenty in Python code too.</p></pre>Graftak9000: <pre><p>b.count? I am from a php &gt; JS background, this is my first toe in the strong compiled hemisphere.</p></pre>climbinglepton: <pre><p>Strange. I would find <code>b.count</code> to make <em>less</em> sense... If you&#39;re going to make the name longer you should at least relate it to bytes, no? Or to the idea of buffering somehow? <code>b.bufSize</code>? I still think <code>b.n</code> wins.</p> <p><code>n</code> is the way the variable is documented in both <code>io.Read</code> and <code>io.Write</code> by the way, hence the reason it seems like a good choice for counting how much was read into the buffer before flushing.</p></pre>weberc2: <pre><blockquote> <p>I am from a php &gt; JS background</p> </blockquote> <p>PHP is much worse than Go: <code>strncmp()</code>, <code>strpbrk()</code>, <code>lcfirst()</code>, <code>nl2br()</code>, <code>strchr()</code>, <code>strcoll()</code>, <code>strcspn()</code> and <code>strpos()</code> to name a few string-related functions from the standard library.</p></pre>Graftak9000: <pre><p>I don&#39;t intend ever using php ever again, I came to go though because I could not cope with node and its management in its current state. So go it is.</p></pre>weberc2: <pre><p>Sure, I thought you were implying that Go is confusing you because &#34;it&#39;s not as clear/verbose as PHP&#34;. The idea made me laugh. :)</p></pre>Graftak9000: <pre><p>Well, the variable names are perhaps a bit too minimalistic for my taste, but yeah php is a monstrosity (I feel similar about Java and its friends) so it was either Python, Node, or Go. It is my first mature language though, so bear with me (it&#39;s my understanding most go programmers have a C-like background)</p></pre>weberc2: <pre><p>I work with Python and Node at work, and they&#39;re both much more painful than Go. In particular, they&#39;re both fundamentally limited in performance and concurrency, but Node and Python are both very difficult to read partially because they&#39;re dynamically typed, but also because JS is naturally ugly and Python&#39;s PEP 8 conventions make it uglier than it needs to be (not to mention Python&#39;s 1-line lambda limit). Further, Python&#39;s standard library mixes camelCase and snake_case conventions. I would take Java over Python or Node, and I would prefer Go over Java.</p></pre>Graftak9000: <pre><p>I do happen to love JS, but I&#39;m not sure if I want to create full blown apps with it. I&#39;m basically looking to make a REST API with Go, and I&#39;ll probably write the web layer in node (write a template once...). For now it&#39;s learning though, and concurrency is always a good thing.</p></pre>mc_hammerd: <pre><p>this is probably not a good example.</p> <p>so b.n is likely just an int counter (position) or size of buffer <code>b</code>. so thats why it was givin a short name</p> <p>the real reason this is all short names is: this is a method func / receiver method.</p> <p>if he used a long name he would just have to type the instance name a lot more:</p> <pre><code>func (ByteWriter *Writer) flush() error { if ByteWriter.err { return ByteWriter.err } if ByteWriter.position == 0 { return nil } newpos, err := ByteWriter.wr.Write(ByteWriter.buf[0:ByteWriter.position]) if newpos &lt; ByteWriter.position &amp;&amp; err == newposil { err = io.ErrShortWrite } if err != nil { if newpos &gt; 0 &amp;&amp; newpos &lt; ByteWriter.position { copy(ByteWriter.buf[0:ByteWriter.position-newpos], ByteWriter.buf[newpos:ByteWriter.position]) } ByteWriter.position -= newpos ByteWriter.err = err return err } ByteWriter.position = 0 return nil } </code></pre> <p>thats a lot of <code>ByteWriter</code>. 16 of em!</p> <pre><code> nextpos, err := ByteWriter.wr.Write(ByteWriter.buf[0:ByteWriter.position]) </code></pre> <p>this is hard to read to some devs. because the font&#39;s [] are not great, imo.</p> <hr/> <p>now IMHO go should include @ syntax like coffee script for receiver classes</p> <p>instead of typing <code>ByteWriter.buf</code> we could just use <code>@buf</code> (or :buf like ruby)</p></pre>Graftak9000: <pre><p>I got online it&#39;s about reading speed, after the first occurrence I interpret a long variable name as a single character an skip it just as fast. As for typing, after two characters I press tab and its auto-completed.</p></pre>boomshroom: <pre><p>Auto-complete isn&#39;t a ubiquitous feature in every single text editor ever and it often doesn&#39;t understand the language your using, so it&#39;s better not to rely on it.</p></pre>mekanikal_keyboard: <pre><p>well, this has absolutely nothing to do with Go</p></pre>weberc2: <pre><p>I don&#39;t find this hard to read at all. <code>err</code> is an error, <code>buf</code> is a buffer, <code>n</code> is a counter (as in mathematics). The only thing I find odd is <code>b</code> as notation for <code>Writer</code>.</p> <p>Personally, I would probably change <code>n</code> to <code>thingCount</code> or something more descriptive, but this is just to make it more familiar for people coming from more verbose languages.</p></pre>Graftak9000: <pre><p>For me it&#39;s the summary of not being familiar with most of the syntax, and seeing single character variables everywhere, which make it appear very abstract (which I now understand is the point). Takes some time to wrap my head around I guess.</p></pre>brokedown: <pre><p>If you&#39;re asking why people use variable names like x, y, and i, it&#39;s because we decided that local variable names with short lifespans didn&#39;t deserve long and meaningful names. Check the Linux Kernel coding style guide, chapter 4. <a href="https://www.kernel.org/doc/Documentation/CodingStyle" rel="nofollow">https://www.kernel.org/doc/Documentation/CodingStyle</a></p></pre>Graftak9000: <pre><p>I understand, but to me there is a difference between short and a single character for everything, looking at my JS a variable name longer than 5 characters is extraordinary. I know Java likes to takeItToTheExtremeWithTheirNaming but there must be a sane middle ground. </p></pre>neoasterisk: <pre><p>This <a href="https://talks.golang.org/2014/names.slide#1" rel="nofollow">talk</a> will answer your questions. </p> <p>In my opinion, it is better to follow the coding style/conventions of each language ecosystem otherwise you will alienate other coders that might want to contribute to your project. Of course in the end it is your code and your rules but usually there is a rich history behind those conventions and especially in the case of Go it is quite significant.</p></pre>Graftak9000: <pre><p>Thanks. My initial reaction has toned town a bit, the exact reason I asked was because I do care about conventions, they just seemed ridiculous at a glance.</p></pre>threemux: <pre><p>This convention should be followed as other gophers will expect it, but it&#39;s probably my least favorite thing about Go. In fact, there is some research that supports the idea that there is a &#34;just right&#34; for identifiers and its somewhere between &#39;x&#39; and &#39;anIdentifierInJava&#39;. </p> <p><a href="http://www.cs.loyola.edu/%7Ebinkley/papers/isse07-id-recall.pdf" rel="nofollow">http://www.cs.loyola.edu/~binkley/papers/isse07-id-recall.pdf</a></p></pre>DigitalDolt: <pre><p>In <em>The Go Programming Language</em> the authors argue that a variable&#39;s name length should be proportional to its lifetime. So you&#39;ll see a lot of local and short-lived variables have terse names, often a single character, while names of variables belonging to aggregate types are longer and more descriptive.</p></pre>dchapes: <pre><p>Surprisingly, it doesn&#39;t seem like anyone has given the link to <a href="http://research.swtch.com/names" rel="nofollow">Russ Cox&#39;s short post about this</a>.</p> <p>Some have specifically mentioned things like <code>i</code> as an index. They seem to forget that this is just notational and nothing more. They might as well suggest that mathematicians shouldn&#39;t be using i, j, etc as subscripts with Σ; nor x, and y in <code>f(x)</code>; or that physicists shouldn&#39;t be using t, v, a, etc for time, velocity, acceleration, etc in their notations. </p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

590 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传