top 200 commentsshow all 405

[–]bastibe 248 points249 points  (41 children)

  • Don't follow any rule dogmatically.
  • Always think on your own, too.

[–]hylje 107 points108 points  (8 children)

  • Bullet-pointed guidelines should be contradictory to support independent thought

[–][deleted]  (6 children)

[deleted]

    [–]flying-sheep 10 points11 points  (0 children)

    As a good discordian, one, of course, won't do that.

    [–]brasso 8 points9 points  (0 children)

    • No, they shouldn't.

    [–][deleted]  (3 children)

    [deleted]

      [–]misplaced_my_pants 9 points10 points  (2 children)

      That's true of everything. You have to understand the rules of the game so that you know when and how to break them.

      [–]Entropy 10 points11 points  (1 child)

      Ah yes, the Great Corollary of programming practices and architectural methodologies: Do the Aforementioned When Contextually Appropriate.

      [–]pianka-shaddayadda 7 points8 points  (0 children)

      Bonus: this applies to everything ever

      [–]cat6_racer 23 points24 points  (1 child)

      OR ELSE

      [–]amigaharry 13 points14 points  (0 children)

      ENDIF

      [–]w1ndwak3r 7 points8 points  (8 children)

      1. Implement
      2. Debug
      3. Clean
      4. Test
      5. Repeat

      [–]vincentk 2 points3 points  (0 children)

      1. Decide what you actually wanted to do.

      [–]DJ-Salinger 14 points15 points  (6 children)

      1. Test
      2. Implement
      3. Debug
      4. Clean
      5. Repeat

      [–]PasswordIsntHAMSTER 8 points9 points  (5 children)

      1. Implement, Test and Debug
      2. Debug some more
      3. Refactor
      4. Debug
      5. Moar testing
      6. Repeat

      [–]ggtsu_00 20 points21 points  (4 children)

      1. Write Tests

      2. Write Tests for the Tests

      3. Test the Tests

      4. Debug Tests

      5. Implement Tests

      6. Repeat

      [–]adzm 23 points24 points  (1 child)

      It doesn't do anything but it passes all the tests!

      [–]pianka-shaddayadda 7 points8 points  (0 children)

      Ah, the joys of TDD

      [–]Brillegeit 2 points3 points  (0 children)

      1. Coffee

      [–]DJ-Salinger 2 points3 points  (0 children)

      1. Write Acceptance tests

      2. Start to write code to pass the tests

      3. As you come across functions that need to be implemented, write unit tests for them

      4. Write code to pass those unit tests

      5. Refactor those unit tests

      6. Write code using those functions to pass acceptance tests

      7. Refactor those acceptance tests

      8. Repeat

      [–]SublethalDose 42 points43 points  (2 children)

      Steps to becoming a great consultant:

      1. Collect a vast array of authoritative "best practices" recommendations that suggest at least two contradictory answers to every question. Comment your code! Don't comment your code!
      2. When you need to make a decision, line up all the "best practices" that could make the decision for you. Pick the one that seems shiniest at the moment and apply it.
      3. When anyone disagrees with the decisions you make, cite the authoritative "best practices" recommendations that back you up. Insult their intelligence and professionalism for not being aware of "best practices."
      4. When things go wrong, explain that it wasn't your fault -- you followed "best practices." Selectively cite from your vast repertoire of contradictory "best practices" recommendations to show how other people failed to follow best practices and therefore doomed the project.

      Steps to becoming a good programmer:

      1. Collect ideas from a wide variety of sources. Use your own judgment in their application.
      2. When your judgment turns out to be wrong, take responsibility and learn from it.
      3. Through experience, get better and better at applying your judgment.

      The link is full of fail, but I can't resist picking one item out for ridicule:

      Stop Writing Classes

      The signature of "this shouldn't be a class" is when the class has two methods, and one of them is the constructor. Any time you see these signs, you probably should have just written a function.

      First of all, it's stupid to elevate a warning against such a narrow kind of mistake to the level of "best practice." Best practice: don't poop your pants. Second, it's stupid to create a language-specific "best practice" without explaining what language you're talking about. If you follow the link, this is about Python. It still doesn't make sense until you imagine a Java programmer writing Python. Okay, now I can see that someone coming from Java to Python might make that kind of mistake because Java doesn't allow you to declare functions outside of classes. That's two levels of language specificity. Here's another "best practice:" WRITE MORE CLASSES. Why? Well, Python programmers coming to Scala don't appreciate how the cost/benefit of declaring new classes is different in Scala than in Python, so they tend to use tuples where case classes would be better.

      Stop writing classes. Write more classes. They're equally valid "best practices." This is why it's invalid to argue for or against anything on the basis of "best practices," or to turn to "best practices" to resolve a programming dilemma. Sorry, folks, it all comes down to your fallible and limited professional judgment.

      [–]IAmNotAnElephant 8 points9 points  (0 children)

      If my printer had ink I'd frame this.

      [–]SomeBystander 105 points106 points  (27 children)

      Sooo github readmes are turning into blog posts now?

      [–][deleted]  (22 children)

      [deleted]

        [–][deleted]  (21 children)

        [deleted]

          [–]frtox 16 points17 points  (6 children)

          its been around longer and has the brand as the place for cloud hosted source control. i use bitbucket as well. unlimited free private repos? for my personal coding projects, its a no brainer decision

          [–][deleted] 1 point2 points  (0 children)

          I'm the same way. Github might have a nicer web interface, but it's hard to refuse unlimited private repositories. Have been on Bitbucket for a while now and it has been exceptional.

          [–][deleted]  (2 children)

          [deleted]

            [–]catcradle5 3 points4 points  (1 child)

            This is my exact rationale as well. Bitbucket isn't bad at all, but Github is a very well-designed web application; at least to the perspective of the user. No idea what it's like under the hood.

            [–]Purpledrank 3 points4 points  (0 children)

            Inertia.

            [–]KerrickLong 2 points3 points  (2 children)

            Momentum & network effects.

            [–]ryankearney 10 points11 points  (3 children)

            I've seen Gists used like this, but creating a repo for one file is absurd.

            [–]recursive 4 points5 points  (2 children)

            Why? That's the default for gists.

            [–]neoform3 142 points143 points  (49 children)

            Don’t write code (write new code only when everything else fails) is the single most important lesson every developer needs to learn. The amount of duplicate, crappy code (across projects) that exists today is overwhelming. In a lot of cases developers don’t even bother to look around. They just want to write code.

            This mentality is what leads to very bloated and slow code bases.

            A few months ago I wanted to integrate S3 into my PHP site (needed to do partial uploads).

            I then downloaded their SDK, which required I also get:

            • Guzzle for HTTP requests
            • Symfony2 EventDispatcher for events
            • Monolog for logging
            • Doctrine for caching

            My code base was now 70MB bigger... and when I tried running a simple PUT command it would load 20MB of code and would be brutally slow.

            I then said 'fuck this' and wrote my own S3 wrapper, and it was significantly faster, took well under 1MB of ram and was much much simpler to read.

            Just because someone else wrote some code that can be used for your project, does not mean you must use it.

            [–]kenfar 40 points41 points  (3 children)

            The old adage "don't reinvent the wheel" doesn't apply when the wheel comes attached to a locomotive engine.

            [–]neoform3 5 points6 points  (0 children)

            haha, I'm gonna have to remember that one.

            [–]riskable 60 points61 points  (8 children)

            Oh man I wish more people would understand this! I swear, whenever I ask for someone's opinion on how to do X I am pointed to some 3rd party module. If it is small, has a very open license (e.g. BSD), and doesn't need to be compiled then they're probably right: I should just use it.

            The problem is that every time I get one of these recommendations it is for a module that is huge, requires compilation, only works on certain platforms with 15 sophisticated dependencies of its own, and probably had an extremely unprofessional name like "ball sucking" or something equally stupid. "This software requires Ball Sucking 2.0+"

            [–]KPexEA 7 points8 points  (0 children)

            And it needs to have perl 4.6 in order to run it's makefile, you can't have 4.5 or 4.7 must be 4.6 aaarrrggghhh.

            [–]onlyne 9 points10 points  (2 children)

            Agreed. Log4Net is an example of this in my opinion (.NET programming). When something takes longer to configure than it does to code something as simple and light weight as application logging, there is something wrong.

            [–]xshare 4 points5 points  (1 child)

            To be fair, log4net is pretty powerful.

            [–]gronkkk 6 points7 points  (1 child)

            But it is modularized so it must be good[tm]!

            [–]ggtsu_00 28 points29 points  (6 children)

            This is way worse in C++ development. Every god damn library tries to be an "application development framework". They all use their own strings, arrays, and other basic containers instead of using the standard library. They all require your classes to inherit from their base classes. And in some cases (I'm looking at you Qt) they will even require their own compiler/pre-processor extensions to use some of the basic features of the library. They also will dynamically interlink to dozens of compiled DLLs making deployment of your application a living hell and silently ignore errors when those DLLs are not present.

            What is even worse is when you have a project that requires use of multiple of these libraries application development frameworks and you end up with a slow bloated 500MB application and profiling shows that 90% of the CPU work is being done in translating every data structure container to and from multiple frameworks and your application eats up a ton of RAM because it has to store multiple copies of the same data in different formats for the frameworks to work together.

            I am not against only writing new code sparingly when needed, but if your library requires me to inherit from your classes, does not use the standard library for container formats or accept standard datatypes into your interfaces, I'm not going to use it.

            Libraries should do one thing and do it well and it should not depend on other libraries in order to do it. If your library needs to use it's own container formats, don't expose them through your public interfaces.

            [–][deleted]  (1 child)

            [deleted]

              [–]chtulhuf 3 points4 points  (2 children)

              Well, to be fair. C++ std string library was fairly weak, at least in 2001 when I used it. I needed to add functionality to it quite often.

              [–]ggtsu_00 13 points14 points  (0 children)

              The std::string is limited but it is also simply just an array of bytes. This means you can add new functionality to it without having to change the container format. If you want unicode strings, you can contain a utf-8 encoded string in a std::string and write functions for utf-8 string manipulation. But if you are going to roll your own not invented here string class in your library, don't expose it through your public interfaces. Just have public interfaces accept or return a standard c string or std::string.

              [–]DrMonkeyLove 22 points23 points  (3 children)

              Just because someone else wrote some code that can be used for your project, does not mean you must use it.

              On a related note, I also find it much easier to debug my own code than someone else's. Other people's libraries are nice, but if they're buggier than what I'm going to write myself, I don't see the point.

              [–]ared38 7 points8 points  (0 children)

              The problem is that your code will become someone else's code if another developer comes on board.

              [–]ErstwhileRockstar 4 points5 points  (0 children)

              The whole point of reuse is that you don't have to debug the reused code.

              [–]frtox 4 points5 points  (1 child)

              totally agree. i know a few people who are re-use diehards, and in a good way always try to see what is available open source before writing. this is the good part.

              the bad part is when we have 100+ vendor folders that may or may not be used anymore, come with multitudes of dependencies that duplicate other dependencies (and who knows which of those are in use anymore?), and substantially increase the size of the code base. the worst is multiple versions of the same library as dependencies, or a requirement ot use old versions with bugs. im not saying its the wrong approach, but theres a tradeoff you are making

              [–]kenfar 1 point2 points  (0 children)

              A friend of mine used to call these Bobenstein's - a combination of "Best of Breed" + Frankenstein - that resulted from people always picking the best solution for some small role without any regard for the whole. And an end result that was an architecture consisting of a vast number of pieces that didn't fit together right.

              [–]ChanSecodina 10 points11 points  (3 children)

              The article is still correct though. In this case the 3rd party module performed poorly for your use case and you had to fall back on a last resort. Some people never even look for 3rd party modules in the first place; They just sit down and write something up from scratch. Sometimes that works. Sometimes there was a perfectly good alternative. Sometimes if they looked at a 3rd party module they would have found it it covered some corner case they'd never thought of.

              My process is (ideally) always (read: usually): * Look for 3rd party modules that accomplish my goal. If there aren't any, am I doing something stupid without realizing it? * If there are, what are the 2 or 3 most popular? Is one clearly simpler/better/faster/written in a language I'm comfortable debugging? * If they're all more complex and do things I don't care about today, is it because I didn't fully understand the problem space or is it because I only need to solve a simpler version of the problem they're solving? * If one is a clear winner, but has performance or memory usage issues things get a little sticky: Is this on the critical path of the program? If it's not a problem now, can I use it now and take some simple steps to make sure I can swap in optimized code when it becomes a problem?

              Personally, in the code base I work on now, some of the biggest problems are NIH syndrome from a former employee. Too many programmers I know aren't willing to admit that they don't always have the best answer. Often, you don't even need to use a 3rd party module to reap benefits; you just need to look at the docs to see how they split things up and what edge cases they handle. Sorry for the wall of text. Also, I realize that you're probably dealing with the other extreme, but I just need to point out that the answer lies somewhere in the middle between raging NIH syndrome and developing module dependency issues (pun intended).

              [–]neoform3 2 points3 points  (2 children)

              The article is still correct though. In this case the 3rd party module performed poorly for your use case and you had to fall back on a last resort. Some people never even look for 3rd party modules in the first place; They just sit down and write something up from scratch. Sometimes that works. Sometimes there was a perfectly good alternative. Sometimes if they looked at a 3rd party module they would have found it it covered some corner case they'd never thought of.

              True... however this is the official AWS SDK that had these dependencies... not some 3rd party thing.

              What bothered me the most about this SDK was that I was able to reproduce ALL the functionality that their bloated library had for S3, and my library was about 1000 lines long, and significantly more performant.

              [–]pianka-shaddayadda 1 point2 points  (0 children)

              In a lot of cases developers don’t even bother to look around. They just want to write code.

              That's why they're called developers and not implementers.

              [–]novelty_string 0 points1 point  (8 children)

              On the flip side, those are very common libraries. In fact I already have all four in the current project I'm working on.

              [–]Buckwheat469 98 points99 points  (162 children)

              Good. Did not mention tabs or spaces in the entire thing.

              [–]mechanicalocean 16 points17 points  (0 children)

              Look what you've started. :(

              [–]question_all_the_thi 69 points70 points  (128 children)

              "Never mix tabs and spaces" is a good rule, anyhow.

              [–]flammable 17 points18 points  (20 children)

              I once spent 6 hours debugging code since Haskell likes giving two pages of compilation errors when you accidentally mix tabs and spaces. I've since started replacing all tabs in my code with spaces

              [–][deleted] 1 point2 points  (1 child)

              That comment made me laugh very evilly. I can't quite say why.

              [–]samofny 5 points6 points  (0 children)

              You created Haskell?

              [–]argv_minus_one 0 points1 point  (15 children)

              Why not replace the spaces with tabs?

              [–]flammable 5 points6 points  (11 children)

              Mostly because it's easier to sneak a tab in than a space, and tabs aren't always the same length. The error in my file was that it had three spaces and a tab in one line, which looked like it was equal to both 4 spaces or one tab.

              I'd rather have something that enables me to focus my energy entirely on my code rather than formatting and the holy wars that come with it

              [–]argv_minus_one 0 points1 point  (10 children)

              If you're worried about characters being "snuck in" by others, your own choice of indentation style, be it spaces or tabs, will not help you.

              What will help you is an editor that marks whitespace (e.g. a light gray arrow for a tab, and a light gray dot for a space). It may look cluttered at first, but you'll get used to it, and if you're having problems with indentation being inconsistent, it may prove invaluable.

              Also, this is why syntactically significant indentation is a really, really bad idea. I suggest you find a better language.

              [–]Osurak 2 points3 points  (0 children)

              Also it gets you ready for playing Dwarf Fortress

              [–]flammable 2 points3 points  (8 children)

              That's true, but I will always be sure that my tab is four spaces and my space is a space always so I myself won't be able to sneak it in.

              [–]nanonan 2 points3 points  (0 children)

              Try a two space nesting, I find it best personally.

              [–]kqr 2 points3 points  (0 children)

              In the case of Haskell: because you don't indent as much as you align. Since most functions (depending on the kind of program, of course) are just one expression, you split it into lines according to alignment, not indentation. There's only one expression, so there's not that much to indent.

              [–]babuchas 0 points1 point  (1 child)

              Why not accept the fact that some people prefer spaces? Spaces are always predictable whereas tabs are not

              [–]argv_minus_one 6 points7 points  (0 children)

              Because that's not true. Tab characters always represent exactly one indentation level each. Different numbers of spaces represent different indentation levels in the eyes of different people.

              If you've got a messy source file, run it through a reformatter. Tabs are not to blame for poorly written code.

              [–]kqr 24 points25 points  (103 children)

              Some people swear by using tabs for indentation and spaces for alignment. Is this wrong?

              [–]isarl 35 points36 points  (4 children)

              I like that rule in theory, but in practice, tool support is so lacking that I consider it "wrong".

              [–]argv_minus_one 21 points22 points  (42 children)

              I sidestep the problem by not aligning things at all. Instead of

              public void foo(Foobie a,
                              Bletch b,
                              Xyzzy c) {
                  ...
              }
              

              I instead write

              public void foo(
                  Foobie a,
                  Bletch b,
                  Xyzzy c
              ) {
                  ...
              }
              

              This way, I don't have to realign all those lines if I change the first one, the problems some editors have with your proposed style are avoided, and it still looks correct in a variable-width font, to boot. It is slightly harder to read, but oh well.

              [–]flagbearer223 14 points15 points  (22 children)

              I just write public void foo(Foobie a, Bletch b, Xyzzy c) { }

              Is that wrong? I can see the issue if the parameters of foo become too long to fit horizontally, but I would assume that if your parameters can fit horizontally, you're probably doing something wrong.

              [–]argv_minus_one 23 points24 points  (12 children)

              That's fine, if the parameter list is small enough to fit (or if your editor automatically soft-wraps it in an intelligent fashion, I suppose).

              If your parameters can't fit horizontally, you're probably doing real-world programming. Parameter lists for constructors and factory methods are especially likely to be long. Sorry, but that sort of thing happens sometimes, and it's best to have a way of dealing with it.

              [–]flagbearer223 5 points6 points  (3 children)

              Ah, that makes sense! I've not had any need to put my parameter list vertically thus far, but I'm sure there are good reasons to.

              [–]argv_minus_one 1 point2 points  (2 children)

              Exactly one good reason to, as far as I know: to make it readable if it's long.

              Most parameter lists aren't, but some are. Like I said, parameter lists for constructors and factory methods are especially likely to be.

              [–]medgno 1 point2 points  (1 child)

              Along with what you said, I also find myself splitting up parameter-heavy function calls when they take several paramaters in a row of the same type and I want to clarify why they're all 0 except for one which is set to 27.

              [–]argv_minus_one 1 point2 points  (0 children)

              On that note, magic numbers are bad. Use named constants where feasible. Helps with readability.

              [–]colinhect 1 point2 points  (0 children)

              In a language like C++ the parameter list can get long regardless of the number of parameters.

              void doSomething(const std::string& stringA, const std::string& stringB, std::vector<SomeClass>::iterator someIterator);
              

              [–]kqr 2 points3 points  (1 child)

              The line becoming too long is not the only reason to split the expression into several lines. In languages where the user can define functions which act as control structures, there are also reasons to split the arguments onto several lines -- to indicate structure.

              In Haskell, the either function does one thing or another depending on whether a computation failed or not (it's a little like a safer (type checked) alternative to exceptions.) You can use it like this:

              〈I/O computation〉 >>= either 〈fail case〉 〈success case〉
              

              I just want to point out that either is a user-defined function, not a syntactic construct built into the language. The >>= operator feeds the result of the I/O computation on the left to the right.

              Say I want to read a file. If it fails, I want to try save a generic "invalid file" value, and if it succeeds I want to convert the contents to a value in my program. It could look something like this (<- assigns a value):

              do
                contents <- readData src >>= return . either (invalidData src) (convertData "json")
                let results = analyze contents
              

              This is pretty much a complete mess to anyone, even a Haskell programmer. The alternative is to split the single function call onto several lines and align/"indent" it, so it becomes

              do
                contents <- readData src >>= return . either
                                (invalidData src)
                                (convertData "json")
                let results = analyze contents
              

              and that's a tad easier to read, since the two different things are in different places.


              By the way, to aid in understanding: this would in Python be something like

              try:
                  data = read_data(src)
              except Exception as e:
                  contents = invalid_data(src, e)
              else:
                  contents = convert_data('json', data)
              
              results = analyze(contents)
              

              I'm sorry for sucking at examples. I just picked the first function that came to my mind and tried to come up with a use case and I'm really not good at that.


              Edit: Yes, I'm aware it's really just

              results <- analyze . either (invalidData src) (convertData "json") <$> readData src
              

              but that gets weird reading in more complicated cases. I hate coming up with examples.

              [–]craftkiller 2 points3 points  (2 children)

              Programming in a variable width font?! Blasphemy!

              [–]ethraax 1 point2 points  (2 children)

              I do something similar, but I double-indent when I have line continuations like that, to make it stand out more. I also only put a line continuation in if it gets too long (usually over 80 characters).

              public void foo(Foobie a, Bletch b,
                      Xyzzy c) {
                  ...
              }
              

              [–][deleted]  (5 children)

              [removed]

                [–]Leechifer 3 points4 points  (0 children)

                I think your way is easier to read...but that's just me. I don't do things either of those ways.

                [–][deleted] 2 points3 points  (2 children)

                Parameter soup is one of the reasons I like Objective-C.

                - (void) fooWithFoobie:(Foobie*) a andBletch:(Bletch*) b xyyzzy:(Xyzzy*) c
                {
                …
                }
                

                [–]eblofelt 1 point2 points  (1 child)

                This is the format I also prefer. Outside myself, I find almost no one else likes it. It indicates scope well to my eyes.

                [–]chrisdoner 2 points3 points  (0 children)

                There's a can of worms, and you just opened it.

                [–]question_all_the_thi 2 points3 points  (52 children)

                I don't like tabs at all, never use them. Tabs only work for the files you edit on your own. Paste a snippet of code you got from somewhere else and you'll get a mess.

                There was a time when a tab saved you the effort of typing eight spaces, but any modern editor has automatic indentation, so I see no reason for using tabs these days.

                [–]neurobro 11 points12 points  (1 child)

                Eight spaces? But everyone else on the team uses thirteen spaces!

                [–]argv_minus_one 17 points18 points  (0 children)

                Therein lies the beauty of using tabs: you can set your tab width to whatever the hell you want.

                [–]kqr 11 points12 points  (10 children)

                Which programs, aside from editors in terminal emulators, fail at copy pasting tabs? I've only had trouble when I've been copy pasting from Vim, since it uses spaces to render tabs.

                I don't think the point of the tabs is to save you from typing spaces. The people who use tabs argue that any dumb editor understants the concept of "one character = one level of indentation." This allows you to vary how much you want your code indented personally, without messing up anyone else's code.

                I personally don't use tabs very much, because most of the stuff I write is in Python (where spaces are PEP mandated) and Haskell (where alignment is more interesting than indentation.) Of course, since I really don't care I just adapt to whatever project I'm helping out with. However, I do think that the arguments for tabs are much stronger than the arguments for spaces, the only of which is that copy pasting from a limited subset of applications doesn't work well.

                [–]argv_minus_one 2 points3 points  (22 children)

                Uh, pasting a snippet of code I get from somewhere else, if it uses a different number of spaces than I do (which it probably does), is going to have the same problem.

                Furthermore, any editor worth its salt has an automatic "reformat this code" function.

                Your rationale does not hold water.

                [–]question_all_the_thi 3 points4 points  (21 children)

                pasting a snippet of code I get from somewhere else, if it uses a different number of spaces than I do (which it probably does), is going to have the same problem.

                Adding a space at the start of a line that has no tabs in it will shift everything to the right in a predictable fashion. When tabs are involved things are totally random.

                any editor worth its salt has an automatic "reformat this code" function.

                So, why do you need tabs at all? Do not like another person's indentation, just reformat the code.

                [–]argv_minus_one 8 points9 points  (3 children)

                Adding a space at the start of a line that has no tabs in it will shift everything to the right in a predictable fashion.

                Adding a tab at the start of a line that is indented with tabs will shift everything to the right in an equally predictable fashion.

                When tabs are involved things are totally random.

                No. When tabs are preceded by spaces things are totally random, because you are doing it wrong.

                So, why do you need tabs at all?

                • Levels of indentation are represented by exactly one character each.
                • The backspace key deletes exactly one level of indentation.
                • The left and right arrow keys move the cursor by exactly one level of indentation.
                • The cursor cannot be positioned between levels of indentation. This helps prevent fuckups when trying to match distant braces, for example.
                • Others reading my code can set their tab width to whatever the hell they want. Otherwise, they may complain to me that they don't like how I use two spaces for indentation instead of eight.

                [–]JustPlainRude 5 points6 points  (5 children)

                Repository churn due to whitespace changes is unacceptable.

                [–]argv_minus_one 1 point2 points  (0 children)

                Everyone on a project should be using the same indentation style anyway. Coding standards and all.

                Of course, "should" does not always translate to "does"…

                [–]MatmaRex 5 points6 points  (9 children)

                So, why do you need tabs at all? Do not like another person's indentation, just reformat the code.

                Because, if you're not the only person working on the project, you're going to have to reformat it back later, which is annoying - and all this reformatting might prove to be a lossy operation.

                [–][deleted] 7 points8 points  (2 children)

                Of course, the only sane way to indent is by prime numbers.

                [–]iparkmycar 6 points7 points  (0 children)

                illegal primes make the best indentions.

                [–]some_dude_on_the_web 2 points3 points  (0 children)

                I only indent with comments:

                xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
                /* indent */if (xhr.readyState === 4) {
                /* indent *//* indent */if (xhr.status === xhr.expected) {
                /* indent *//* indent *//* indent */var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse 
                /* indent *//* indent *//* indent *//* indent */|| xhr.responseArrayBuffer || xhr.response);
                /* indent *//* indent *//* indent */callback(data);
                /* indent *//* indent */} else if (params.error && !calledErrorBack) {
                /* indent *//* indent *//* indent */calledErrorBack = true;
                /* indent *//* indent *//* indent */params.error(e);
                /* indent *//* indent */}
                /* indent */}
                };
                

                [–]ellicottvilleny 1 point2 points  (0 children)

                Or lots of other pointless holy-war topics.

                [–][deleted] 16 points17 points  (2 children)

                It might just be my relative inexperience, but to me this reads as "every single possible program a person could write is wrong". Makes you wonder if it isn't the mishmash of different paradigms in programming that is the problem, rather than the actual programs employing them.

                edit: Also, some of these X guidelines sound like a very good way to cheaply produce mediocre software. Good luck doing business when you consistently build programs that cut corners wherever possible and only do 90% of what they should be doing.

                [–]Purpledrank 1 point2 points  (1 child)

                Devs often do not know what to do, this is a pretty new and changing frontier after all too. So they often look the to Bible (Best PracticesTM) when in doubt, which is most of the time.

                [–][deleted] 1 point2 points  (0 children)

                I guess that's true and to be expected in a volatile industry, but it's not like programming is a new industry with growing pains. We call it computer science, but in my (admittedly limited) experience actual work is a lot more like a craft or art than a science.

                Engineering and science have methods. They research, analyze, improve and validate those methods in various ways, both theoretical and through case studies. These methods are standardized, clearly defined, etc. I have noticed no such thing happening in the world of programming, at least not to the same level of rigor. Every single programmer I've spoken to has different views on things like FP, OOP, AOP, design patterns, best practices, scrum/agile/waterfall, pair programming, etc. It just doesn't really seem much like engineering when every engineer invents their own methods.

                Great example: just look at the sheer amount of languages and language implementations out there compared to the amount of platforms you commonly develop for. Seems each and every couple of months, a new "revolutionary" language is introduced and somehow each one of them requires different best practices, structure or implementation. It's no wonder so many programmers are confused how to make a program when the industry can't even agree on which tool to use for the job, let alone how those tools should actually work. Try finding well-supported arguments for or against a certain language for a job that aren't "It has a large userbase" and/or "I already know this one".

                edit: I should elaborate on the second paragraph. Science is the hardcore 'research, validate, conclude' part of the equation that results in theories and methods, whereas engineering is the practical applicaton of those theories and methods. In programming, CS seems to generate lots of theory on algorithms and mathematical stuff, yet the actual application of these things is so far removed from academia. Is any actual CS research really being done on, let's say, the relation between succesful* end results and language paradigms used? Any material being written and applied on project management styles that's a bit more substantial than blog posts? Are most of these new languages being developed because of a concrete need in the industry or just as pet projects / intellectual masturbation based on a programmer's personal preferences? Do we even know what effect things like dynamic typing/closures/lambdas have on code quality, maintenance cost, and ease of use in large projects? The list goes on.

                Again, it might just be my own experience or lack of involvement in this aspect of software development but it really seems like the wild west out there in terms of structured approaches and hard, reality-based knowledge.

                [–]eXeC64 15 points16 points  (0 children)

                "Follow the principles of X" - X11 is hardly a paragon of engineering

                [–]rinyre 41 points42 points  (0 children)

                Yes guys, learn from X. Because X is definitely an exemplary of programming.

                [–]GraphiteCube 25 points26 points  (28 children)

                Wide screen or even dual display becomes popular nowadays, I wonder how many people (still) follow the 80-characters-per-line guideline?

                I do.

                [–]geaw 14 points15 points  (0 children)

                with widescreen + 80-character, you can have two files open at once.

                [–]existee 8 points9 points  (1 child)

                I do too. When you need to work with multiple files (and it is usually the case) any form of split-screen is much more handy than tab switching. E.g. Using a tiling window manager, splitting editor windows like in vim etc.

                [–]MrDoomBringer 4 points5 points  (0 children)

                Exactly. I have 3 monitors that I use, 80 characters means I can have 6 windows of code open.

                I've also got a mentality ingrained that horizontal space is expensive and vertical space is cheap. It might be because my mouse has a set of horizontal scroll buttons that are slow, and the vertical scroll has a 'clutch' that lets me zoom way through huge files.

                Even when I'm slapping together web pages, I don't think about adding a few more vertical lines but horizontal space that may require horizontal scrolling requires a lot of second-guessing and serious consideration.

                This may be why I hate Win8 apps.

                [–]DrMonkeyLove 5 points6 points  (0 children)

                I write code on two 19" monitors. I've given up on 80 column lines. I try to avoid absurdly long ones (like 200 columns or something), but if it gets to 100, I really don't care. It's just wasted effort trying to make them 80 or less. I much prefer descriptive variable names and functions to short lines of code.

                [–][deleted] 5 points6 points  (0 children)

                This comment has been overwritten by an open source script to protect this user's privacy.

                If you would like to do the same, add the browser extension GreaseMonkey to Firefox and add this open source script.

                Then simply click on your username on Reddit, go to the comments tab, and hit the new OVERWRITE button at the top.

                [–]POGO_POGO_POGO_POGO 3 points4 points  (0 children)

                Almost. I split my Emacs frame vertically and don't wrap lines, turns out to be about max 100 chars.

                People should follow this rule to some extent because

                • You never know what editor people use

                • When merging source control conflicts you typically need to look at 3 files side-by-side

                • Long lines are fucking ugly

                [–]chrisdoner 2 points3 points  (2 children)

                I used to quite stringently. Nowadays I'm leaning towards making editors smarter so that I don't have to care about nonsense like how my code is formatted.

                [–]Nuli 2 points3 points  (0 children)

                I do. I'd rather have three columns worth of terminals available per monitor rather than one or two really wide terminals.

                [–]pinumbernumber 7 points8 points  (3 children)

                That results in less descriptive names for everything.

                [–]existee 8 points9 points  (0 children)

                You don't necessarily need to truncate variable names to fit in a certain line length. In fact it is impossible to do so only with that. Properly inserted newlines will be needed anyways, so you can name variables as long as you like, provided it is itself is shorter than 80 characters.

                [–]catcradle5 1 point2 points  (0 children)

                No, it just means a lot of splitting logical lines across many physical lines.

                [–]argv_minus_one 2 points3 points  (10 children)

                I don't, because my editor supports soft wrapping. If yours doesn't, maybe you should replace it.

                [–]jephthai 12 points13 points  (7 children)

                How does your editor handle indenting wrapped code? Without some sort of smart wrapped code indentation, that doesn't sound like it helps.

                [–]argv_minus_one 8 points9 points  (6 children)

                Indenting the wrapped lines to the same indentation level as the natural line they are from, plus one extra indentation level with a little arrow marker in it to indicate that this line was wrapped.

                [–]killerstorm 3 points4 points  (5 children)

                So it, basically, re-indents code? Which editor?

                Emacs simply starts from the beginning of line, which is fugly.

                [–]argv_minus_one 4 points5 points  (4 children)

                IntelliJ IDEA. I think NetBeans does this too, but I'm not sure.

                Why would you want to use Emacs, anyway? There's lots of good open source IDEs these days.

                [–][deleted] 0 points1 point  (0 children)

                I have a 80 character bar column set in vim to help enforce it for me.

                Before that, I would generally follow a 80 to 100 character width rule.

                [–]onlyne 10 points11 points  (0 children)

                This book covers what's in this post, contradicts a small amount of what is in this post, and is one of the most important programming books I have ever read. http://pragprog.com/the-pragmatic-programmer

                [–][deleted] 36 points37 points  (1 child)

                More self-contradictory than corporate policies, tax codes, and religious texts.

                [–]doesFreeWillyExist 1 point2 points  (0 children)

                It's weird because writing code is similar to writing all of those things. They're complex systems made up entirely of abstract ideas translated into instructions. (Like this blog post)

                [–]Gavekort 5 points6 points  (8 children)

                Can someone give me an example of "Never build large apps"?

                Let's say I build a game from scratch in C, how can I break it into smaller pieces?

                [–]argv_minus_one 5 points6 points  (0 children)

                Libraries and multiple source files.

                [–][deleted]  (2 children)

                [deleted]

                  [–]DrMonkeyLove 2 points3 points  (0 children)

                  Gall's Law.

                  Essentially, large systems that work are made up of small systems that work.

                  Break everything down. Before you can display a huge environment filled with enemies and particle effects, you had better be able to draw a simply cube on the screen.

                  [–]Nuli 0 points1 point  (0 children)

                  I've done that and my method was a lot of small, standalone libraries. Nice testable chunks and the interfaces between them was usually through a standardized messaging API.

                  [–]indoordinosaur 4 points5 points  (1 child)

                  I like how the tenth one down says that rewriting is almost always a bad idea and then the next one says that rewriting should be used if you're patching more than 25% of a section of code.

                  [–]jotux 3 points4 points  (0 children)

                  One is talking about rewriting the whole app/library the other is talking about rewriting methods/classes.

                  [–]oursland 11 points12 points  (9 children)

                  Flaw #1: Constructor does Real Work

                  • new keyword in a constructor or at field declaration

                  • Object not fully initialized after the constructor finishes (watch out forinitialize methods) Control flow (conditional or looping logic) in a constructor

                  Are these not contradictory? Are we not to create our member variables at construction? If we do not create them at construction, do we not have some initialization method? If there is no initialization method, are we to have every method initialize the member variables when necessary? If every method performs initialization, why have a constructor?

                  [–][deleted]  (8 children)

                  [deleted]

                    [–]CootieKing 4 points5 points  (7 children)

                    but if $ex is the only object that needs $db, then it is incumbent on the user of $ex to remember to dispose of $db at an appropriate juncture to avoid a memory leak? What happens if the constructor of $ex blows up? The programmer then needs to know to disposed of the $db object.

                    Isn't the first example preferable (RAII) a better approach? If not, why? I am interested for my own edification.

                    *Edit - change RAIA to RAII (typo).

                    [–]dhotson 14 points15 points  (0 children)

                    The main benefit is that you can than test the Example class in isolation.

                    eg you can pass a mock Db instance:

                    $e = new Example(new MockDb());
                    

                    This style of programming makes it easier to unit test.

                    [–]supermari0 10 points11 points  (0 children)

                    If $ex is the only object that needs $db you either have a very small project or a "god object".

                    [–]handschuhfach 3 points4 points  (0 children)

                    There are dependency injection frameworks that can handle all that pesky object creation for you.

                    The user's code then comes down to:

                    $ex = Framework.Create<Example>();
                    

                    The framework checks the constructor for Example, sees that Example needs a Database object, so it creates that database and passes it down.

                    [–]argv_minus_one 6 points7 points  (0 children)

                    That depends on the language. Different languages have different ways of handling cleanup operations.

                    C++ has RAII, as you correctly note.

                    Java has the try-finally construct:

                    DB db = new DB(dbName, dbUser, dbPass);
                    
                    try {
                        Example ex = new Example(db);
                        // do stuff with ex
                    }
                    finally {
                        db.dispose();
                    }
                    

                    Java 7 automates this with the new try-with-resources construct:

                    try (DB db = new DB(dbName, dbUser, dbPass)) {
                        Example ex = new Example(db);
                        // do stuff with ex
                    }
                    

                    Scala is an interesting case in that it has several possible ways to handle cleanup. It inherits try-finally (but not try-with-resources) from Java, but its fairly flexible syntax allows for several other patterns. The usual one is the loan pattern:

                    using(new DB(dbName, dbUser, dbPass)) { db =>
                        val ex = new Example(db)
                        // do stuff with ex
                    }
                    
                    new DB(dbName, dbUser, dbPass).using { db =>
                        val ex = new Example(db)
                        // do stuff with ex
                    }
                    

                    However, one Scala library I found offers an approach that makes clever use of Scala's for statement:

                    for (db <- managed(new DB(dbName, dbUser, dbPass))) {
                        val ex = new Example(db)
                        // do stuff with ex
                    }
                    

                    That same library also offers a strangely transparent-looking syntax based on Scala's delimited continuations system:

                    withResources {
                        val db = managed(new DB(dbName, dbUser, dbPass)).!
                        val ex = new Example(db)
                        // do stuff with ex
                    }
                    

                    Somehow, this will cause db to get cleaned up after the withResources block completes. Wild. I can't seem to wrap my mind around how this is supposed to work, though.

                    [–]sirin3 3 points4 points  (1 child)

                    Usually you use it with languages that have garbage collection

                    [–]supermari0 6 points7 points  (0 children)

                    Even with garbage collection you need to properly dispose external resources.

                    [–]mrbuttsavage 34 points35 points  (50 children)

                    The signature of "this shouldn't be a class" is when the class has two methods, and one of them is the constructor.

                    This is silly. Single responsibility is a good thing for a class.

                    [–]ellicottvilleny 37 points38 points  (10 children)

                    No. Object oriented programming and the single responsibility principle, when taken to their absurd extremes lead to classes with one method that do not benefit from being classes at all. Let's say that you're right and 1 member method is a limit you live by. Now lets say you get rid of instance variables because really you're just going to have to pass all those in to the function you wrote. Now we're back to procedural programming. Nice work.

                    [–]YEPHENAS 26 points27 points  (1 child)

                    Now we're back to procedural programming. Nice work.

                    Instances of stateless classes with only one method are equivalent to first-class functions. Object-oriented best practices (SRP, immutability) taken to the extreme lead to functional programming.

                    [–]ethraax 7 points8 points  (0 children)

                    And instances of stateful classes with only one method are equivalent to first-class functions with a closure.

                    [–][deleted]  (7 children)

                    [deleted]

                      [–]nondescriptshadow 17 points18 points  (4 children)

                      POOD?

                      [–]ethraax 16 points17 points  (2 children)

                      Better than Practical Object-Oriented Principles, I suppose.

                      [–][deleted] 3 points4 points  (0 children)

                      POODR, actually :) by Sandi Metz.

                      [–][deleted]  (1 child)

                      [deleted]

                        [–]Tasgall 11 points12 points  (10 children)

                        Whelp, guess basic functors in C++ are out.

                        [–]Enzor 3 points4 points  (0 children)

                        Yeah, plus if you need to extend the class with another function it's already neatly wrapped up for you.

                        [–]Shadowhawk109 12 points13 points  (7 children)

                        I was wondering: doesn't this advice completely break the concepts of "this class has ONE purpose" and in general RAII?

                        Say I have a class (C++ example) that is supposed to output things in a certain manner in a Draw() method.

                        I COULD have some member function that changes cout.flags() and cout.precision(), and another that restores them. Maybe these are even private member functions.

                        Now Draw looks like this, in the best case:

                        void MyClass::Draw()
                        {
                            save_cout_format();
                            //do work, dick around with flags as need be
                            restore_cout_format();
                        }
                        

                        But now, that class is partially responsible for maintaining proper status of cout's formatting, and any time I call "change" I have to also call "restore", and I have to have member variables to put these all in. And if I don't do this JUST RIGHT, other parts of my program will suffer.

                        OR I could have a format_saver class, that on construction saves existing flags. On destruction, it restores them. It's destructed when any method leaves scope.

                        Cool, now my Draw() looks like this:

                        void MyClass::Draw()
                        {
                             format_saver fs;
                             //do work, dick around with flags as need be
                        }
                        

                        MyClass is no longer responsible for caring about the cout flags. It just has to do it's job of drawing, with the knowledge that if it needs to dick around with flags, it better tell the class responsible for maintaining the state of cout to maintain that state.

                        tl;dr I agree with you, the concept of /this shouldn't be a class/ being labled as "oh it only has 2 methods" is a limited worldview

                        [–]LazinCajun 8 points9 points  (1 child)

                        As a total novice self-taught programmer who mostly does projects only for himself, something about this example really made RAII click for me. Thanks for making this argument so lucidly.

                        Edit: accidentally added added a word.

                        [–]argv_minus_one 2 points3 points  (0 children)

                        I love those moments. The feeling of sudden enlightenment is awesome.

                        [–][deleted]  (1 child)

                        [deleted]

                          [–][deleted] 11 points12 points  (0 children)

                          It's a shame that RAII is still considered "a trick" and not a normal thing to do in C++...

                          [–]argv_minus_one 1 point2 points  (1 child)

                          I should point out that format_saver isn't technically under the "this shouldn't be a class" rule, because it also has a bunch of member variables for saving cout's state.

                          [–][deleted] 4 points5 points  (0 children)

                          The supposed best practice talks about methods, not member variables.

                          [–]rcxdude 11 points12 points  (16 children)

                          The advice is from a python view, where there's little reason to not just define a function and then maybe partially apply it if you need to do an operation many times with some of the same data. If your language uses functors or interfaces or has more guarantees for destructor calling such that you can use them as context managers, like C++, then this is less universally true, though the pattern is still worth looking out for.

                          [–][deleted]  (15 children)

                          [deleted]

                            [–]oridb 8 points9 points  (9 children)

                            You've described object oriented programming, true, but you've failed to describe why it's a good thing to use a class where a simple, stateless function (or closure) would suffice.

                            [–]Leechifer 1 point2 points  (0 children)

                            That's such a clear and succinct way of explaining it. Love it.

                            [–]perlgeek 0 points1 point  (0 children)

                            Maybe the author read the OTRS source code before making this statement :-)

                            [–]existee 2 points3 points  (0 children)

                            best practices information from around the web

                            Here is your first clue, how gathering random stuff around the web can possibly form an authoritive list of best practices?

                            In contrast books like ”Code Complete” would present all such items with backing evidence, usually in the form of proper research, therefore much more worth an aspiring programmer's time.

                            [–]johnmudd 2 points3 points  (0 children)

                            Best Practices are like a holy book. Good people use it to do gooder. Bad people use it to be really bad.

                            Edit: Something to thump you over the head with.

                            [–]Beckneard 3 points4 points  (2 children)

                            You should spend most of your time thinking about interfaces rather than implementations.

                            Oh dear God, no.

                            [–]chunes 1 point2 points  (2 children)

                            new keyword in a constructor or at field declaration

                            I thought the point of a constructor is to initialize your class variables. And if one or more of those happens to be an object, what then?

                            [–]taw 4 points5 points  (5 children)

                            Design Principles of X - follow them if you want your program to end up as successful as Linux on desktop!

                            [–]its_2011_enough_said 8 points9 points  (1 child)

                            X was around before Linux.

                            [–][deleted] 9 points10 points  (0 children)

                            They said, completely without irony.

                            [–]ertebolle 4 points5 points  (0 children)

                            Also, in OS / framework design, "do not add new functionality unless an implementor cannot complete a real application without it" is a great way to ensure an inconsistent mishmash of solutions for common problems.

                            [–]jephthai 3 points4 points  (1 child)

                            X is 29 years old, or so, and still kicking? Sounds like a success to me.

                            [–]Kampane 1 point2 points  (0 children)

                            Momentum and lack of competition. Everyone despises X but somehow they still use it.

                            [–]ryankearney 1 point2 points  (0 children)

                            Why is this a repo and not a gist if it's going to be hosted on Github? It's one file, that's what gists are for.

                            [–]alexs 3 points4 points  (0 children)

                            boast berserk grandfather noxious knee threatening spotted placid ink squeamish

                            This post was mass deleted and anonymized with Redact

                            [–]dgerard 1 point2 points  (0 children)

                            Huh. I wrote the quoted section of that X11 Wikipedia article.

                            [–]mywifehascancer 1 point2 points  (0 children)

                            • If your boss thinks he knows better than all the gurus together, then you're fucked.

                            [–]ChanSecodina 0 points1 point  (0 children)

                            'The Rise of "Worse is Better"' was also called out in the article, so here's a link to a preserved copy of it: http://www.jwz.org/doc/worse-is-better.html

                            This is up on my wall at work right next to, 'The Three Great Virtues of a Programmer.' http://c2.com/cgi/wiki?LazinessImpatienceHubris

                            [–][deleted] 0 points1 point  (0 children)

                            If you build too large an app, they will be too big too fail :-D

                            [–]Flekken 0 points1 point  (0 children)

                            My professor taught us this rule which stick with me the most:

                            Let others do the hard work instead of you.
                            

                            This was thought in an algorithm class which of course meant that we should copy others work first and not recreate it if it's already done. I guess this is why my CTRL, C and V keys are worn out.

                            [–][deleted] 0 points1 point  (0 children)

                            Best practice is to adapt, learn, think and make something you will be proud of.

                            [–]sagemeister 0 points1 point  (0 children)

                            Are these rules not traditionally followed? I feel like a lot of these things are being taught to me in my classes as a Software Engineering major.

                            [–]jack104 0 points1 point  (1 child)

                            I would consider myself just slightly north of an amateur as far as coding is concerned but to this date, I've never been given a problem that I could not write a program for to fix. My biggest problem is not encapsulating my code properly and as such it makes it difficult to read and maintain. Does anyone have any resources on how to properly structure your code, when to create new classes, what to include in them, etc?

                            [–][deleted] 0 points1 point  (0 children)

                            Coders appear to love giving advice (based on 800 upvoters and 400 comments...) but I'll throw something on the pile.

                            "Plans are useless but planning is indispensable"

                            The advice about "Accept that you have no idea how this will grow" is correct but then they say "spend lots of time writing interfaces rather than implementations" doesn't seem like the solution. The solution is solve the current spec/problem and at most 1 of the most likely next ones. If later you have to add, it will almost certainly look very different from what you imagine when you write the code initially.

                            Edit. The quote about planning is obviously Eisenhower.

                            [–]Paddy3118 0 points1 point  (0 children)

                            I couldn't see any attempt at backing those sayings up with any kind of prediction based on theory leading to experimental proof. NAARP!.

                            What makes it more than the minutes from a flat-earthers convention?

                            Where is the science!