23 ms·
Things I learnt the hard way in thirty years of software development
- Kreotiko 7y agoI would add: learn to write properly, something the author didn’t. A fellow not native speaker.
- js8 7y agoI think the most difficult lesson is that good software is like cheese or wine. You have to let it age, to find the proper way to approach the problem; adding more developers will not make the process faster.
- pmarreck 7y agoit’s a pretty long read... clearly the author did not learn brevity in his coding, or that his blog’s color scheme does not contribute to readability also re: Gherkin: Just don’t cucumber. If you focus on integration test technology like Cucumber or headless browser drivers, they will absolutely balloon your test suite runtime and it is partly because they are extremely inefficient (testing the same things over and over and over again such as “set up a logged-in user with 3 assets” for 90% of the test cases in the suite). Avoid. Maybe not entirely, but in large part.
- _asummers 7y ago> it’s a pretty long read... clearly the author did not learn brevity in his coding, or that his blog’s color scheme does not contribute to readability It's also riddled with typos which made reading it hard. There's some wisdom in there, but it was clearly written in an editor without spell/grammar checks. Maybe there should have been a section about rereading your own work before sending to your team/prod? =)
- reallydontask 7y agoI would guess that based on name and link to a book, he wrote, in Portuguese, that the chap's first language is not English
- Kreotiko 7y agoAs a fellow not native speaker I don’t think this should matter the moment you choose to use English. Also, personally, it wasn’t just the grammar that put me off but also all the aggressive colloquialism used.
- reallydontask 7y agoI give non-native speakers a lot more leeway for typos, grammar and odd expressions for, hopefully, obvious reasons. A lot of people use English as it's the language of tech, which means that the potential audience is significantly larger.
- tomelders 7y ago> Turn off comments
- pmarreck 7y agoThere should be a way to vet negative people in some way that comments wouldn't be toxic
- MichaelApproved 7y ago> "it’s a pretty long read... clearly the author did not learn brevity in his coding" Brevity shouldn't be a virtue of coding. The best code is self-documenting code and self-documenting code is rarely brief. To quote Wordpress PHP Coding Standards: In general, readability is more important than cleverness or brevity. https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#clever-code https://make.wordpress.org/core/handbook/best-practices/codi...
- pmarreck 7y agoIf you want code brevity, at all, PHP is not your language (nor is Go, nor is Java)
- pytester 7y ago>If you focus on integration test technology like Cucumber or headless browser drivers, they will absolutely balloon your test suite runtime and it is partly because they are extremely inefficient Between unit tests (fast, unrealistic, tightly coupled, catches fewer bugs) and integration tests (slower, more realistic and catches more bugs) I virtually always pick the latter. I'm happy to trade CPU churn for "catches more bugs". CPU time is cheap.
- pmarreck 7y agoIt is not a dichotomy. Ideally you’ll have lots of unit tests and a few integration tests, all valid. I’m scarred by seeing test suite runtimes (THE most important element of programmer productivity IMHO) completely balloon after focusing too much on integration tests. There is a world of productivity difference between a 1 minute test suite and a 40 minute (or 4 day) test suite
- pytester 7y ago>It is not a dichotomy. It is a dichotomy. You do not want the same thing being covered by two different types of test. Duplicated test coverage means duplicated maintenance. >There is a world of productivity difference between a 1 minute test suite and a 40 minute (or 4 day) test suite Not in my experience. Tests can easily run while I'm at lunch, overnight, working on something else or, if time is really of the essence, in parallel. If I'm running an individual test while developing anything that runs in under a minute has no effect on my productivity. Tests that don't catch bugs are a far, far bigger deal.
- lostmyoldone 7y agoOptimising for our reading effort is not a given, neither in length or style. It's a choice. Insinuating incompetency when choice is clearly a reasonable explanation is in my opinion quite disingenuous. If you don't like the style, at least say so clearly, if you have to. But why do you have to? The authors tip to disable comments, I fully understand. I find writing hard, and I could never cope with all the things - except the actual text - people find the need to complain about.
- molteanu 7y ago> Spec first, then code and then later > Be ready to throw your code away Then why would it be useful to have the spec first if you're expecting to throw it away anyway? Better combine this advice, > Write steps as comments with a higher level language, and write code instead of comments, and have fun developing what you think is the product you need. You'll see plenty of corner cases, learn tons of new stuff about your domain that you didn't even think existed and then you'll want to start over since many of your initial assumptions will be wrong anyway by that time or you'll see new extra features that you couldn't have possibly discovered without actually having a toy product to play with and try new ideas with. Tests? No, definitely not on the first run. Maybe only for documentation purposes in legacy systems. But don't take away all the fun by starting with tests. You'll paint yourself into a corner. This seems like 30 years of experience in a corporate environment. I would take these recommendations with a grain of salt. I would venture to say that whoever starts with "I have x years of experience" or "I'm an Y language developer" is mostly bulshitting you or doesn't really know what he's talking about, so he'll need to have a badge to shove it up your face to demonstrate his qualities.
- MrGilbert 7y ago> This seems like 30 years of experience in a corporate environment. Well... That's where the money's at, right? > Tests? No, definitely not on the first run. Maybe only for documentation purposes in legacy systems. But don't take away all the fun by starting with tests. Kindly disagree. In a corporate environment (at least the one's I've worked so far), you HAVE to start with the tests. From my experience, people maintaining your code after you've left the company (or you are sick, whatever) will be grateful to have a testsuite that can verify the edge cases are still working after their changes have been deployed. Also, when the first working lines have been written, there was no way we would revisit them to write test on top. I need tests to verify that what I've just written actually works. Others might create a "ExampleConsoleApp1" for this, but then I can also write a test.
- molteanu 7y ago> Maybe only for documentation purposes in legacy systems. > people maintaining your code after you've left the company That's what a legacy system is. I agree. That's a good use of tests. But don't start WITH them. You'll build rigid systems. > Well... That's where the money's at, right? Agree with this also. But this is (or should be) hacker news, so we look for better ways to make software, regardless if it makes money or not. Or maybe we should rename it Financial Times?
- bobm_db 7y agoI really like this one: > Documentation is a love letter to your future self This seems like a brilliant way of transcending what feels like a drudge-job, making it into something really meaningful.
- tomelders 7y agoWriting code is also UX. some future user will have to understand it. More often than not, that future user is you.
- ehnto 7y agoWhich is why: Verbosity is not bloat. Abbreviations are a code smell. I remember encountering a platform in a language before namespacing was introduced in that language, and it had names for the classes like `Platform_Catalog_Model_Product_Simple_Collection`. It looked really silly, but I always knew what I was working with at a glance. It was honestly a really nice developer experience.
- snarf21 7y agoNot that documentation is bad but it is rarely correct. Now you have to spend time trying to match documentation that doesn't match the code you see. I always prefer a different approach. There is no need to document what a function does, that is self evident from stepping through it. The thing that should be included in the code is the WHY, meaning why does this function even need to exist and how does it fit into the architecture? Now an accurate high level architecture diagram and function raison d'etre telling you everything you need to know with much less risk of not having an accurate and up-to-date documentation process.
- mannykannot 7y ago> Not that documentation is bad but it is rarely correct. Rarely? I often turn to the documentation to check the capabilities, syntax and semantics of the languages and interfaces that I use. If it were only rarely correct, I would be in trouble. If you are talking about application code specifically, my experience is that documentation is too rarely present to be an issue.
- SamuelAdams 7y agoFor as much grief as Medium gets, it sure would help blogs like this. The font color is a poor choice considering the background, the font itself isn't that common for reading long text forms. Not saying Medium is perfect, but it does help standardize the display of all these random, one-off blogs.
- kgraves 7y agoAlternatively, I use reader/distill mode, the color scheme on this blog made me squint and almost damage my eyes that I nearly stopped reading immediately until I switched on reader/distill mode. I agree, for a much wider (programming) audience, Medium would suit better for this blog.
- enlyth 7y agoPress F9 if you're on Firefox :)
- sadness2 7y agoSmall price to pay?
- jp_sc 7y agoI strongly disagree. This is like saying that every store everywhere should be a Walmart so one doesn't have to adapt to the organization of other stores. In my opinion, the style of the blog is as important as the content because we are dealing with the self-expression of a person here. The colors and fonts were conscious decisions, and presenting the data in the most efficient and standardized form is not the first priority. (Also calling it a "one-off" blog is kind of mean. Sure it might the first and the last time you ever read a post there, but that blog has more than one hundred posts, so it's not a "one-off" for the author.)
- astine 7y agoRight. The font at least is a monospace font common in terminals. It's a clear conscious design decision that technical readers are likely to pick up on.
- 7y ago
- chewxy 7y ago> A long time ago, a small language made the rounds by not evaluating expressions when they appeared, but when they were needed. > Lisp did this a long time ago, and now most languages are getting it too. I'm not sure if this is correct. You can probably write a macro for lazy eval, but by default lisp is a CBV almost-lambda calculus. Or you could pass around quoted things, I guess
- phoe-krk 7y agoF-expressions were a thing back in the day. https://en.wikipedia.org/wiki/Fexpr https://en.wikipedia.org/wiki/Fexpr Possibly the closest thing available in Common Lisp are Lisp macros - they receive their arguments unevaluated, and are free to utilize that input for further computation.
- chewxy 7y agoTIL. I only came across fexprs briefly on LtU once and never looked more into it. Thank you.
- drderidder 7y agoI like the point "The function documentation is its contract". I experimented using JSDoc instead of TypeScript on a recent javascript project and have found it so enjoyable, partly for that reason.
- edw519 7y agoExcellent post! Thank you, Julio! This could make great bulletin board material in some other format, but there's just too much here for that. I started my reply by cutting and pasting the gems with my little follow-up, but quickly realized that would take all day. There just so much good stuff here. So instead I narrowed it down to just one: Code is humans to read. ALWAYS. Optimization is what compilers do. So find a smarted way to explain what you're trying to do (in code) instead of using shorter words. This really strikes a nerve because in 40 years of programming, most of my problems have not been with building code myself, but with trying to figure out what my predecessor had written. I bet I've wasted 20 years of my life refactoring the crap of others who would have benefited greatly by reading posts like this one first. There's lots to think about. Lots to smile and agree with. And lots to disagree with (OP reminds me a little of myself, a caveman who often claims to know "the one right way" :-) If you don't have time to read this now, bookmark it and come back later. One good idea from this can make a big difference.
- maxxxxx 7y ago"This really strikes a nerve because in 40 years of programming, most of my problems have not been with building code myself, but with trying to figure out what my predecessor had written. I bet I've wasted 20 years of my life refactoring the crap of others who would have benefited greatly by reading posts like this one first." I also curse a lot about code my predecessors have written but I bet my successors will curse at my code too :-)
- majewsky 7y agoThings I learnt the hard way reading this article: Headlines with `font-size: 1em` make a large article unnecessarily hard to skim.
- mrob 7y agoYou can remove all the author's CSS with one click of Firefox's Reader View. The HTML is structured just fine, so this this works very well.
- LoSboccacc 7y ago1em can not be at fault it's literally 'whatever font size parent has' the culprit is somewhere else.
- proaralyst 7y agoWhich is specifically the body text size, no?
- LoSboccacc 7y agoyeah, but that's the issue: hs and ps are both coded to the same size which happens to be 1rem i.e. 1rem hs would be ok if you'd had 0.8rem ps, and conversely you'd have the same issue if both were coded to be 2rem
- tasty_freeze 7y agoctrl - will decrease the font size on your browser. (ctrl + increases; ctrl 0 resets it to the specified size).
- JoeAltmaier 7y agoGood stuff, until it broke down into coding style.
- RocketSyntax 7y ago"Types say what you data is" Are you saying to first check the type of your data before running a boolean so that you can catch high level things that are Null when they should be char or int?
- joaobeno 7y agoHappy to see some things I learned the hard way with 15 years... Man, I wish I had this level of knowledge when I was 20...
- fnord123 7y ago>ALWAYS use timezones with your dates This is bad advice. NEVER use timezones with your dates because there is only one timezone: UTC. Anything else is a presentation format. Of course, if you are in a system that already committed the cardinal sin of storing datetimes with timezones then you have to deal with it. Alas.
- kstenerud 7y agoPlease please please please don't perpetuate this idea that all stored timezones must be UTC. Timezones are always necessary, and while they can often just be UTC, they can't always be [1]. [1] https://technicalsourcery.net/posts/time/ https://technicalsourcery.net/posts/time/
- fnord123 7y agoThat is an interesting post and does discuss the issue of always-local-to-me calendaring and planning future dates when you don't know what the political regime will do with those times in the future. Those are fair points. For recording all events (i.e. times you see in logs, 99.9999% of timestamps you will see), there should only be one timezone: UTC.
- Lendal 7y agoWhat if you're building a $350M machine that weighs many tons, located deep inside a concrete facility and will never ever be moved? The people who operate this machine years in the future will read a date on a log file or database table and make decisions that could affect the lives of millions of people, all of whom live in the same time zone with said machine. I don't want these people to be forced to convert UTC in their heads when there is no reason for it except for some abstract rule created by someone who doesn't know the first thing about this machine and its purpose, or the people who live there.
- fnord123 7y agoIf you have very specific design constraints, please don't use advice from random people on the internet as though it's absolute gospel.
- chamilto 7y ago> When you're designing a function, you may be tempted to add a flag. Don't do this. Here, let me show you an example: Suppose you have a messaging system and you have a function that returns all the messages to an user, called getUserMessages. But there is a case where you need to return a summary of each message (say, the first paragraph) or the full message. So you add a flag/Boolean parameter called retrieveFullMessage. Again, don't do that.'Cause anyone reading your code will see getUserMessage(userId, true) and wonder what the heck that true means. What about in languages with named parameters? I think keyword arguments solve this issue pretty well.
- rntz 7y agoIf the name is mandatory, as it is in Smalltalk, then this basically solves the issue. If the name is optional, as it usually is in eg. Python, then there is a temptation for the writer to omit it, which means the reader won't know what "True" or "False" stands for. Are there languages besides Smalltalk and its descendants with mandatorily-named parameters?
- rand_r 7y agoIn Python 2, if you need to, you can force people to use kwargs by defining the function in the form of def f(*args, **kwargs): and then making sure any params you use in the function come from kwargs, and raising an error if args is non-empty. Python 3 has a nicer way of doing the same thing, that I can’t remember. (Sourced from the book “Effective Python: 59 Specific Ways to Write Better Python”.)
- shakna 7y ago> For a long time, I kept a simple programming rule: The language I'm playing at home should not be the same language I'm using at work. This allowed me to learn new things that later I applied in the work codebase. Though I've found this helpful in expanding what I can do, or how well I can do it, what I find using a different language at home than at work does best is prevent burnout. I can be reckless, and play with the language, because I don't have the tired patterns of my day trying to rigidly enforce best practices and cover all edge cases. My mind can relax and do the wrong thing if I want, and I don't have the autoformatter or linter in mind. I don't have a dozen rules that will spit red errors if I step out of line. Those things are all good for work. The application must be solid, and the user deserves stability. But when I'm hacking together a game for myself that I never intend to release, I just want to experience the fun side of programming without the hard part.
- kstenerud 7y agoOne more point from my 20 years experience: Keep your development environment deterministic and instantly rebuildable. You should ideally be able to take your hard drive out, put in a new one, install a fresh OS, run 1 script, and be completely up and running in less than an hour. As an added bonus, this means that you can replicate your development environment on any machine very quickly and easily, which makes losing your laptop during travel only an inconvenience rather than a travesty. I've hacked together some scripts for that here [1], although I really should convert them to ansible or something. [1] https://github.com/kstenerud/virtual-builders https://github.com/kstenerud/virtual-builders https://github.com/kstenerud/ubuntu-dev-installer https://github.com/kstenerud/ubuntu-dev-installer
- smilliken 7y agoI've always agreed in principal, but fell short in practice until I started using Nix[1]. Nix makes it significantly easier to pull off by verifying the hashes of all inputs, eliminating non-determinism in builds (timestamps, usernames, etc), eliminating dependencies on OS packages/files/etc, and allowing you to pin to a specific snapshot of all packages. Pardon the evangelism, I'm just a happy user. [1] https://nixos.org/nix/ https://nixos.org/nix/
- corrigible 7y agoI'm setting up a new laptop next week, mostly for Go/Python dev, zero front-end requirements... What's your workflow on Nix like?
- GlennS 7y agoI like to combine Nix with direnv (and direnv-mode for Emacs - there are also similar plugins for most other editors). Then you can `cd` into your directory and your environment appears. The downsides are that there is a steep and long learning curve, and that your colleagues will not understand what you've done. I also use NixOps to actually deploy my code at the moment, but I will probably be switching to Terraform shortly as I need some tools like AWS autoscaling groups, which NixOps doesn't support. These are probably helpful: https://nixos.wiki/wiki/Development_environment_with_nix-shell https://nixos.wiki/wiki/Development_environment_with_nix-she... https://github.com/direnv/direnv/wiki/Nix https://github.com/direnv/direnv/wiki/Nix https://nixos.org/nixpkgs/manual/#sec-language-go https://nixos.org/nixpkgs/manual/#sec-language-go https://nixos.org/nixpkgs/manual/#python https://nixos.org/nixpkgs/manual/#python
- draw_down 7y agoIn half that time, basically everything I have ever built has ended up in a ditch. I suppose I have learned a lesson or two since I started, but any lesson fairly pales in comparison to that fact.
- koonsolo 7y agoGreat lessons! Although it didn't include one that I had to learn the hard way, multiple times: Your throwaway prototype will be the codebase for the project. In my career, I've seen multiple throwaway prototypes that were hacked together. None of them ended up in the waste bin. "Just add X and Y and you're done". "But this is just a quick hack to show the interface, there is nothing behind it!" "Yes, and the interface is fine, so why start from scratch? Just add the rest". Now I know: I never build throwaway prototypes ever again, it's always a base for the project to come.
- sadness2 7y agoHow about this: Code can add value when it's a lot lower quality than we think it needs to be. Customers will pay for even a crappy solution if you are addressing the right problem. Don't over engineer. But also employ staff for the explicit purpose of gradually increasing the quality of codebases which need to continue to churn.
- mgkimsal 7y ago> But also employ staff for the explicit purpose of gradually increasing the quality of codebases which need to continue to churn. No one ever wants to hear that part.
- sadness2 7y agoThat is either a problem with leadership, or with the way the role is being framed to them. Perhaps this will help your case: https://martinfowler.com/articles/is-quality-worth-cost.html https://martinfowler.com/articles/is-quality-worth-cost.html
- jmcqk6 7y agoI put it this way: There is no floor to how bad code can be and yet still make people money.
- hinkley 7y ago
- robodale 7y ago> Learn when you can't code anymore. Learn when you can't process things anymore. Don't push beyond that, it will just make things worse in the future. I cannot agree more. (18 years developer here). On those days I just kept pushing, I mostly ended up correcting my poorly-created code the next day. When you know you're done, be done, or at least switch to the lowest mental energy task you can do. Sometimes staring into the screen is that lowest mental task.
- diggan 7y ago> Sometimes staring into the screen is that lowest mental task For the sake of your eyes (and perhaps well-being), don't just stare into the screen without doing anything. If you have a free moment, take your eyes off the screen and look out the window (or at nearest wall if you have none)
- WhompingWindows 7y agoThis is when I take a slow walk around the building or outside for a few minutes.
- bluejekyll 7y ago> Unit tests are good, integration tests are gooder I would personally rephrase this as unit tests are necessary, as are integration tests, as are end-to-end tests. The testing pyramid: write most of your tests as unit tests, then write a bunch of integration tests, and finally throw in a few end-to-end tests. > Tests make better APIs Yes! This is such an important point. A perfect example I love is that globals and even thread-local values make testing hard, and that’s reason enough to avoid using them. > Make tests that you know how to run on the command line Again great advice. I would also add, get your tests running as early as feasible. This saves you rewriting APIs and other decisions that might make testing, even deployment (which you need for end-to-end tests), significantly harder. Anyway, this entire set is a great read, and I agree with much, but not all.
- sadness2 7y agoI'm with Julio on this one. The triangle ought to be a diamond, with the integration tests being the fattest part. This is a level where tests can be at the component level, where they can correspond to specifications which are comprehensible to stakeholders (which helps keep developers accountable to focus test effort on things that really matter), and where refactoring of component internals do not require corresponding refactors of test code. This creates challenges, 90% of which are resolved by applying the same good development practices (re-use, abstraction, performance) to your test code that one is accustomed to applying to application code.
- twic 7y agoThe model i like, keeping to the monumental theme of the test pyramid, is a testhenge: http://www.ox.ac.uk/sites/files/oxford/styles/ow_medium_feature/public/field/field_image_main/shutterstock_625998422.jpg http://www.ox.ac.uk/sites/files/oxford/styles/ow_medium_feat... You need a thin layer of high-level tests (controller and/or browser) covering the entire application, and then columns of lower-level (integration and unit) diving deeper into it where there are areas of particular complexity or risk.
- bluejekyll 7y agoYou seem to imply that I think integration tests aren’t valuable. But I’m not saying that. What I’m saying is that it’s easier to produce unit tests that cover sections of code and test their contract across edg-cases easier than it’s to do the same with integration tests. An example: Let’s say you’re writing a DNS resolver. You need to parse all of the various RDATA portions of records. It’s far easier to write an exhaustive suite of unit tests that verify the code is parsing those data elements properly and throw in many tests for edge-cases that might mean insecure software if done incorrectly. But it’s absolutely invaluable that we also have integration tests that verify an entire Message parses, and even moves through the entire stack from parsing to response. But why construct an entire Message when all you need to test is the RDATA? It’s easier and less complex test code to localize the RDATA test, and then to do a smaller set of Message based tests that verify the message moves through all the stacks properly. Then popping all the way up the stack, you actually need to generate network traffic and send real DNS queries and verify that those work. That means multiple processes in your end-to-end test. Trying to produce a full set of tests that would validate individual edges cases in all RDATAs would be an extreme amount of redundant code, and also would fail due to many other reasons not related to an RDATA change, thus making it more time consuming to track down a failure. Each area of tests is absolutely important and all are necessary for different reasons.
- maxxxxx 7y agoOne thing I have learned in almost 30 years of SW development: work somewhere where the CEO has at least a basic idea of your work and sees value in your work, not just cost. Work somewhere where people care for the craft and it’s not only about “business” goals.
- ravroid 7y agoThis is an excellent piece of advice. Of the five companies I have worked for, the two where I was disconnected from leadership were where I felt the least valued (and consequently less motivation). Of the three where I worked directly with leadership, I was treated with significantly more respect and felt a much stronger sense of purpose.
- redleader9345 7y agosee relevant post from 2017 https://news.ycombinator.com/item?id=15740926 https://news.ycombinator.com/item?id=15740926
- 1PlayerOne 7y agoCan you give examples of companies that fit your description?
- deleted 7y ago[deleted]
- maxxxxx 7y agoApple under Jobs, Google, Facebook, MS under Gates, lots of smaller companies. Probably the ones where a founder is still CEO.
- savrajsingh 7y agoAnd the founder was a software engineer
- ellius 7y agoLife is essentially a big collection of systems or games, and choosing to play the wrong ones is worse than playing the right ones badly. You can learn tricks to get promoted at some place that has a shitty culture, shitty bosses, etc., but at the end of they day all you'll have done is won the wrong game.
- thieving_magpie 7y agoI enjoyed reading that. I recognized a lot of things I used to do and a lot of things I currently do. It's nice to gain perspective on that.
- peterwwillis 7y agoSomething I learned: K.I.S.S. is the most important principle in technology, but keeping technology simple while still adding value and utility is really hard. Example: how can we improve on the design of the bicycle, but keep it simple? You could add expensive composite materials, design a new gearing mechanism, create new complex geometries based on wind tunnel experiments... all of those are more advanced, but complex; simple is a tough nut to crack.
- agentultra 7y agoType systems exist on a spectrum. A rich type system is better at documenting your code than comments are if the compiler and it's type system are sound: the comments can be wrong, the types cannot. A sufficiently expressive type system can check your logic for you. Push as much of your propositions and predicates into the types as possible. Data types are better than exceptions, return codes, etc for the majority of unexceptional cases. Conditions and restarts are better than exceptions. Sometimes crashing is not an option when your computer is flying in the air with a human. In addition to specifications -- often a bunch of boxes with arrows will not be sufficient. There are a range of tools to check your designs from automated model checking to interactive proofs. When the problem is difficult to understand on its own then the solution is probably even harder -- a good sign you should consider using one of these tools to make the problem clear and guide you to the right solution.
- JamesBarney 7y agoI agree with everything you said, except >: the comments can be wrong, the types cannot. If you're arguing comments are valuable but type constraints are a better way to express requirements than I agree and sorry for the long post. But I've seen a lot of comment hate on hackernews and I feel like I have to defend comments. I really think comments can be especially valuable. They're valuable when reviewing code because they tell the reader what the developer was attempting to do, not necessarily what they did. Not everything is expressible in every type system. Even something as simple as "this reference can't be null" isn't expressible is many languages. Comments are easier to read than type names, a sentence is much more expressive than code. Especially code that is tricky due to performance or domain complexity. Type and method names can rot too. If you have a method that starts with get that someone adds a little bit of updating logic to making the method name misleading. And comments can be kept up to date easily by just adding an item to your code review checklist "Ensure comments match code".
- agentultra 7y agoComments are useful and type constraints are a better way to express specifications. It varies on the level of expressivity and soundness of the type system employed as to how valuable comments are. In my experience there's an inverse relationship: the more expressive the type system, the less valuable are comments. This is true in so far as the types get richer the more they can express with less ambiguity than prose. In a way this makes the comments that do exist in such a code base even more valuable since they describe far less and are probably filled with interesting information such as why certain propositions are important, etc. However when you're working in languages without a static type system or a rather weak one, comments can be necessary and invaluable. Update To clarify, in a type system as rich as a dependently typed language, given an inductive definition of vectors, and a type; Agda, for example, can often find the solution (the term) that implements the type. You could add a comment if you wanted to but you'd only be elaborating on what is already obvious by the type signature. This does scale beyond trivial examples such as vector products and into the realm of business logic; it's possible to encode state machines this way. Code comments of this kind of code end up looking superficial. In a more common FP language like Haskell, often derided (even by me) for it's lack of commenting and documentation, seems to be that way precisely because once you get used to understanding how to reason about types... well it gets redundant... and the compiler cannot check that comments are correct with respect to the term level code. The comments are sparse and rich instead of redundant and full of exposition. That's not to say that comments don't exist! Other poster have given many good examples where they are definitely necessary. I ascribe to the rule that there's a balance and too many comments are not helpful just as too few are as well.
- Doubl 7y agoI don't see much wrong with true or false as arguments. Beats having two functions instead of one which is his preference.
- deleted 7y ago[deleted]
- surajs 7y agoThis is awesome, thank you!
- herodotus 7y ago> Spec first, then code > If you don't know what you're trying to solve, you don't know what to code. I like this, but I would add "Always read the spec before you code".
- MichaelMoser123 7y agoWhat i learned: keep a log of problems solved and things that slowed me down. Helps me to be more aware of what I am doing, hope it will keep me from shooting at my foot, at least occasionally.
- Raphmedia 7y agoThe sections on work relations are golden. If there is anything you should remember after reading this, it is these points.
- tuananh 7y ago> Don't use Booleans as parameters ah, he must have forgotten about named parameter
- kgwxd 7y agoJust happened to follow Julio on Mastodon yesterday, he commented on this thread there: https://functional.cafe/@juliobiason/102292722895801015 https://functional.cafe/@juliobiason/102292722895801015
- amelius 7y ago> Spec first, then code I wish I could make my boss understand the importance of this one. In his mind, the best coding strategy is: 1. build prototype 2. add feature 3. goto 2.
- physicles 7y ago> Keep a record of "stupid errors that took me more than 1 hour to solve" I’ve been doing this for the last three years, but electronically, and it’s amazing. In my home folder there’s a giant text file that’s like my personal log file. It gets a new line at least once an hour, when cron pops up a box and I type in what I’m working on. And for those times when I’m working on stuff that’s perplexing, I write to it as a stream of consciousness — “tried this, didn’t work” “wonder if it could be due to xyz” “yep, that was it.” I’ve used it a few dozen times to either look up how I solved a weird problem, or why I decided to do something a certain way. I’ve even built pie charts of how I spent my time in the last quarter by sampling it Monte Carlo style.
- stormthebeach 7y agoDo you have this cron script hosted anywhere?
- AnimalMuppet 7y agoI keep a log of "stuff I had to look up how to do". Mine isn't "stupid errors" so much as stuff like "what are the flags to get the compiler to show you the assembly code it produces".
- unimpressive 7y agoReminds me of: http://messymatters.com/tagtime/ http://messymatters.com/tagtime/ Which is a pretty well formed solution in this vein, unfortunately written in Perl.
- dsmithn 7y agoany experience with newtagtime.com ?
- jupake 7y agoFastastic! This is so deliciously language/framework/editor/OS agnotic. Nothing quite like experience to make you wish you could go back in time, with all your current knowlege, and take over the world.
- vmlinuz 7y agoHaven't read all of these yet, but a couple stood out as matching recent experiences... "Future thinking is future trashing": we had a good engineer with a bad tendency to write complex generic code when simpler specific code would work. In one case, he took a data structure and wrote a graph implementation on top of it - it was only ever used once, by him, and I recently rewrote it in about 15 lines of structure-specific code. In another case, he wrote a query builder to make it easy to join data from a new service with our legacy DB, which makes the high-level code simple, but the full implementation much more complicated, and means incoming engineers can't obviously see what implementation to use. His last week at the company was... last week. "Understand and stay way of cargo cult": Today, I was reviewing someone's code, when I saw a language construct I didn't recognize, and which made no sense to me. I asked him what it was meant to do, and if he could give me a link to somewhere which described the construct - he said no, he'd mostly just copied it from someone else's code. I asked 'someone else', and he pretty much said it was useless, he's worked in so many languages that he gets confused about language idiom/construct sometimes, he writes his code like he'd write a letter to a friend, and it wasn't like anyone was reviewing his code at the time anyway. I said I wasn't going to take his stuff out of the existing codebase, but I wouldn't let anyone copy his useless code in future, and linked him to https://blog.codinghorror.com/coding-for-violent-psychopaths/ https://blog.codinghorror.com/coding-for-violent-psychopaths...
- hamburglar 7y agoThis is a great, great list, but what the heck is this: > This is what most people get wrong about adding booleans to check the number of True values. This appears in two different sections. Who are all these people adding booleans as if they're integers? It's like someone wrote a whole treasure trove of sensible life advice that included "this is why most people have trouble when they use a dry-erase marker as a toothpick."
- mixmastamyk 7y agoLooks like a weird side effect of Javascript being exploited by the unscrupulous.
- wiz21c 7y agoWell mines : Unicode is trickier than you think, there are some date-time that don't exist, transactions are trickier than one (usually) think, don't use floating point for money (because many people don't understand floating point), a quick fix always introduces another bug, any contract (WSDL, json-schem, whatever) is full of holes, integrate with others first, legacy database are full of bad/unexpected data,...
- AtlasBarfed 7y agoCan I get some further commentary from people with 50 years of experience in software development?
- pier25 7y ago> Solve the problem you have right now. Then solve the next one. And the next one. Amen to that.
- coryfklein 7y agoOMG I never have encountered this idea for function deprecation in libraries but I think it is hilarious: > (A dickish move you can do is to create the new functions, mark the current function as deprecated and add a sleep at the start of the function, in a way that people using the old function are forced to update.) This idea is sure to waste lots of people time, lead to angry emails, and is probably worse than just changing the function signature in-place without any deprecation schedule at all.
- brianpgordon 7y agohttps://twitter.com/johnregehr/status/920691341738123264 https://twitter.com/johnregehr/status/920691341738123264
- strken 7y agoThe description of cognitive dissonance is wrong. It's not holding two things in your head at once[0], it's the feeling you get when you believe two contradictory things. [0] that's closer to https://en.wikipedia.org/wiki/Working_memory https://en.wikipedia.org/wiki/Working_memory
- simplify 7y agoYes, and it's also not as severe or "a sign of being stupid" as many think. Cognitive dissonance occurs in situations as simple as walking to a store and discovering the store is closed.
- 1123581321 7y agoIt’s also used in marketing to describe what happens when a buyer’s expectations are not met by the product, and is entirely used to fault the seller and the seller’s marketing.
- Const-me 7y agoMost of them are awesome, but some are questionable. > don't add flags/Boolean parameters to your functions. Many languages have strongly-typed enums for them, makes calling code readable, e.g. getUserMessages( user, eMessageFlags.Full ). Especially useful for more than 1 flags. > ALWAYS use timezones with your dates UTC usually does the trick? > UTF8 won the encoding wars UTF8 used on the web a lot, but OP seems to be generalizing their experience over all programming, not just web development. > when your code is in production, you can't run your favorite debugger. No but I can run my second favorite, WinDBG. A crash dump .dmp file is often more useful for fixing the bug than any reasonable amount of logging. > Optimization is for compilers Compilers are not that smart. They never change RAM layout. I've recently improved C++ project performance by an order of magnitude replacing std::vector everywhere with std::array (the size was fixed, and known at compile time). Before I did, profiler showed 35% time used in malloc/free, but the cost of vectors was much more because RAM latency.
- lifeisstillgood 7y agoIf a function description includes an "and", it's wrong yes :-)
- luord 7y agoI agree... on the actual technical points. Particularly the bits about design patterns and thinking about the users first.
- dheera 7y ago> "Don't use Booleans as parameters" ... except I think it's perfectly fine in languages that support named parameters. In fact this isn't even specific to booleans. Say we're using Python, draw_rect(width = 5, height = 10, top = 5, left = 6) is much more readable than draw_rect(5, 10, 5, 6)
- turingbike 7y agoNamed parameters _might_ be my favorite part of Python. I don't understand why every language doesn't have them.
- simplyinfinity 7y agoC# also has them and it's amazing !
- astrange 7y agoObjective-C and Swift also. Though my favorite implementation is AVISynth, the best language and most interesting execution model nobody uses.
- Izkata 7y agoFor languages that don't (and depending on the usage, maybe ones that do), I'd like to throw out another possibility for those who haven't seen it before: Fluent interfaces draw_rect(5, 10).at(5, 6) draw_rect().from(5, 6).to(10, 16) It's one I'd be careful with though, as it can be easy to end up with something less readable.
- blablabla123 7y ago> Learn to recognize toxic people; stay away from them > You'll find people that, even if they don't small talk you, they will bad mouth everything else -- even some other people -- openly. So true. It has happened to me so often - actually at most brown-field projects - that when I get onboarded, someone is telling me in which bad state this and that is, even how bad this and that person is supposed to be. Although I tend to be optimistic, when the project seems to be nicely challenging at first (not only from the code), I somehow take over this negative attitude for the rest of the project. I think people should be able to informally talk about projects, even gossip sometimes. But it has its limits, especially team/project leads should IMHO be really careful about taking negative stances on certain projects/people/teams. In fact the limits to mobbing are fluid. For me this is the single biggest annoyance in any job.
- ShamelessC 7y ago> So true. It has happened to me so often - actually at most brown-field projects - that when I get onboarded, someone is telling me in which bad state this and that is, even how bad this and that person is supposed to be. I certainly don't want to encourage any sort of toxicity like this. I will say, however, that I recently started a new job. People haven't been particularly welcoming so far but I finally managed to bond with someone over a discussion of the skill gap that exists between some of the employees and the lack of quality code produced by a few of the stubborn veterans. It wasn't just a bonding experience either. I was able to learn more about the nature of the organization and how I can help to improve things in the future. It also had a calming effect because I was originally pretty intimidated by some of these veterans but now I know they're just flawed humans like the rest of us.
- blablabla123 7y agoPretty close to that was also my last experience. But having seen that before, I wasn't intimidated by all these accomplishments. In fact running a linter objectively showed the overall low code and design quality. Anyhow, complaining doesn't help but trying out things and gradually improving. In fact it's possibly even a good opportunity because nobody else wants to touch such code so there's room for creativity (of course within the limits that the stakeholders are fine with).
- neves 7y agoSome of the things depend on the language getUserMessage(userId, True) in Python can become getUserMessage(userId, getUserMessagesFull=True)
- prometheus76 7y agoWhat happens if I set it to False, and what happens if I don't set it? Does it default to sending a summary, or does it send a null? I don't see how having named parameters eliminates the problem OP is talking about.
- graphememes 7y agoThe only one I have an issue with is > Future thinking is future trashing It really depends on what you're building, and how long term the project will be around. Git vs Javascript Frameworks
- therufa 7y ago> Data flows beat patterns (This is personal opinion) When you understand how the data must flow in your code, you'll end up with better code than if you applied a bunch of design patterns. this one is priceless.. I had so many arguments in my past with cocky devs about this topic. Don't get me wrong, patterns are good, but it's only a small part of coding. Also patterns aren't there to follow them as they where the law, but bend them to your needs. One doesn't even necessary needs to be implemented to 100% as it is in the "book". So yes, this part of the post i'm very fond of, it's really wise.
- cgrealy 7y agoI cringe whenever I hear someone talking about "what pattern to use here" (I cry if the answer is "singleton"). Patterns are a way of describing code. They are meant as a common language to use when explaining a codebase to another dev. If you are writing code with the express intention of "using X pattern", you're doing it backwards.
- lliamander 7y ago> Also, remember that most people that are against CoCs are the ones that want to be able to call names on everyone. There's a XKCD comic which points out how people who claim to "hate drama" tend to be the most dramatic people[1]. That's how I tend to perceive projects that put a lot of emphasis on their CoC. The more they emphasize it, the more I expect pettiness, vindictiveness, and bad faith. [1]https://xkcd.com/1124/ https://xkcd.com/1124/
- astrange 7y agoIt's not surprising that a large or corporate project would need an HR department, which is what the CoC is. Anyone who objects to that probably has never worked at a large company, or used a forum with no mods. But the important thing isn't the rules, it's that there's someone to enforce them. Ideally, the rules exist to constrain them, not you.
- lliamander 7y agoWhatever you may think about how a CoC ought to work, my observation about they work in practice (and the people who push them) remains the same. > Anyone who objects to that probably has never worked at a large company. I can assure you that's false.
- m3kw9 7y ago#Future thinking is future trashing
- sethammons 7y ago> People get pissed/annoyed about code/architecture because they care > ... Yeah, you don't like that hushed solution 'cause you care" was one of the nicest things someone told about myself. This is very similar to a foundation that we repeat at work. Everyone is trying to make things better, we might not agree on the how, but we must agree on the intent. When you assume good intent, conversations go much, much better. It can be a great way to frame disagreements. "We are disagreeing here because we care."
- nunez 7y ago> Understand and stay way of cargo cult. "Cargo cult" is the idea that, if someone else did, so can we. Most of the time, cargo cult is simply an "easy way out" of a problem: Why would we think about how to properly store our users if X did that? _cries in kubernetes_
- rurp 7y agoI'm curious about the "Don't use Booleans as parameters" point. I primarily write Python and like to use keyword arguments in these cases. So the function call would look like get_message(full_message=True) Is this an OK pattern for Python but not some other languages, or am I writing more confusing code than I had realized?
- ndiscussion 7y agoThat's exactly what the post is warning against. It's really hard to explain without a concrete example, but basically, I would make two functions: get_full_message and get_partial_message or something like that
- ShamelessC 7y agoIs it safe to say that using named keyword arguments mitigates this issue?
- Izkata 7y agoIf you add a safeguard to the function itself that disallows full_message as a positional arg, so no one is able to write "get_message(False)", then it's okay. The key here is the reader being able to tell at a glance what the args are/do, without needing to hunt down documentation.
- prometheus76 7y agoWell, if I'm reading that, I'm wondering what gets returned if I set that parameter to false. Does it return a summary of the message, or does it return the first word or does it return null? Using named parameters doesn't answer that question any more clearly than OP's example.
- WalterBright 7y ago> You can be sure that if a language brings a testing framework -- even minimal -- in its standard library, the ecosystem around it will have better tests than a language that doesn't carry a testing framework, no matter how good the external testing frameworks for the language are. D not only has it as a library, it's a core feature of the language. As incongruous as it sounds, builtin unittests have been utterly transformative to how D code is written. Built in documentation generation has had the same effect.
- WalterBright 7y ago> You can create the new functions and mark the current one as deprecated, either by documentation or by some code feature. Another D feature that is so simple in concept but miraculous in its effects - a "deprecated" attribute that can be applied to declarations. It enables plenty of warning given to users before it is removed.
- astrange 7y agoWell sure, but GCC and co have that too. It's a pretty good counter to people who think you should always use -Werror. One wrong deprecation could take you a month to fix!
- WalterBright 7y agoMost of these sort of lists are crap. But this one is good. I'm amazed I agree with nearly all of it. (>40 years in the business!)
- WalterBright 7y ago> I tried to become "paperless" many times. At some point, I did keep the papers away, but in the very end, it really do help to have a small notebook and a pen right next to you write that damn URL you need to send the data. I thought I was old-fashioned because I keep one of those spiral notebooks on my desk. It's invaluable. I've never been able to take quick notes using a computer. When I fill up the notebook, I run it through the scanner, toss it and get another.
- deleted 7y ago[deleted]
- cgrealy 7y agoA lot of people in this thread have argued that named parameters mean you can add bool params to functions. e.g. getUserMessage(userId, fullMessage=true) While that can help, I'd still argue against it unless your language has some mechanism to force use of name. Because if you can omit the name (i.e. getUserMessage(userId, true)) then someone will omit the name.
- cgrealy 7y ago> Always use a Version Control System Please tell me no-one is writing anything without a VCS in 2019. > One commit per change Amen, brother. > You're responsible for the use of your code That's a tough one. Code is a tool, like any other. If you're making a gun, then you have to accept that your product will kill people. But if you're making a hammer, it's not really fair to hold you responsible when someone goes postal with it. > Learn from your troubles This. So much this. If you're not doing this... the rest is worthless.
- raveenb 7y agogood one!
- rainhacker 7y ago> Beware of micro-aggressions > Toxic/micro-aggressors are only fixable if they are YOU This is a good thing to keep in mind. But the article doesn't provide any suggestion when you are a victim. Anyone has tip(s) to deal with a micro-agressor?
- davidjnelson 7y agoThe authors recommendation seemed to be to change jobs.
- GuB-42 7y agoThat's interesting because even if I agree with most technical points, I went the opposite way for most of the general points. The big one is: start with the specs, then code. I used to think that, wasting time making plans for an end result that ends up completely different. Now, I prefer to start coding right away. Anything goes, it just has to be code. Why code? That's because it keeps my feet on the ground. And because it is the early phase, I can still change things. Chances are that most of that early code will be scrapped, maybe several times. No big deal, I may have lost a few days of coding, but I have a much clearer view than if I spent that time writing specs. As for the documentation vs code, I spend all my experience points into reading and understanding code. I sometimes even force myself not to read the documentation, going straight for the code instead. Comments are lies. For me, documentation will always be an afterthought, for others. For me, I have the code, and if I have trouble reading it later, that's because it is bad code, not because it lacks documentation, and I try to learn my lesson, and maybe rewrite the offending parts. For the social part (code of conduct, micro aggression, etc...), my strategy when things become unpleasant is to go technical. The bigger the asshole facing me is, the more deeply technical I go. Here two things can happen. Either the asshole is incompetent, and because he doesn't want to look too much like a fool, he usually leaves me alone. The other is that the asshole turns out to be really good, and in that case, the interaction may not turn out to be the most pleasant, but at least, there is something to learn.
- dorusr 7y ago> If a function description includes an "and", it's wrong Unless you have procedures. Also, the 'don't add boolean switches' doesn't count for Powershell, as you can use named switches that are false if not added. For other languages you could add constants