I am compiling a rules of programming mindset for my team: What are yours?

Viewed 3904

I have been working on a list for a while that helps me share the why of programming approach and thought as much as how to do something.

For this, I wanted to build a list of things that are:

  • best practice,
  • best thought,
  • best approach...

that help a programmer's ability to analyze, think, approach, solve and implement in the most effective way.

I have seen dozens of incredibly valuable comments in questions throughout Stack Overflow, but I couldn't find a place where we keep them together. There is the most controversial opinion on Stack Overflow. However, I'm just looking for sagely insights that can be shared and help my team, and I approach and solve problems better through better programming.

Hopefully this can be one place to gather the one or two liners that are concise, profound and easy to share, repeat, review. If we keep it to one rule per answer it might be easiest to vote up/down.

I'll start with the first.

DRY - Don't Repeat Yourself - In code, comments or documentation.

64 Answers

Always leave the code a little better than when you found it.

Don't be afraid to admit "I don't know" and ask.

10 minutes asking someone could save a day pulling your hair out!

KISS - Keep it simple, stupid.
Pick the simplest solution that works.
Don't make things (too) complicated before they need to be.
Just because everyone else is using some complicated framework to solve their problem, doesn't mean you have to.

Maintainability is important.

Write code as if the person who will end up maintaining it is crazy and knows where you live.

Someone else won't fix it.

If a problem comes to your attention, take ownership long enough to ensure it will be taken care of one way or another.

Don't optimize unless there's a demonstrable problem.
Most of the time when people try to optimize code before it's been proved necessary, they'll spend a lot of resources, make the code harder to read and maintain, and achieve no noticeable effect. Sometimes they'll even make it worse.

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."
- Donald Knuth

How hard can it be?
Don't let any problem intimidate you.

Don't Gather Requirements -- Dig for Them

Requirements rarely lie on the surface. They're buried deep beneath layers of assumptions, misconceptions, and politics

via The Pragmatic Programmer

Follow the SOLID principles:

Single Responsibility Principle (SRP)

There should never be more than one reason for a class to change.

Open-Closed Principle (OCP)

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

Liskov Substitution Principle (LSP)

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

Interface Segregation Principle (ISP)

Clients should not be forced to depend upon interfaces that they do not use.

Dependency Inversion Principle (DIP)

A. High level modules should not depend upon low level modules. Both should depend upon abstractions.

B. Abstractions should not depend upon details. Details should depend upon abstractions.

I think almost everything that is listed under "The Zen of Python" applies for every "Rules of Programming Mindset" list. Start with 'python -c "import this"':

The Zen of Python, by Tim Peters

  • Beautiful is better than ugly.
  • Explicit is better than implicit.
  • Simple is better than complex.
  • Complex is better than complicated.
  • Flat is better than nested.
  • Sparse is better than dense.
  • Readability counts.
  • Special cases aren't special enough to break the rules.
  • Although practicality beats purity.
  • Errors should never pass silently.
  • Unless explicitly silenced.
  • In the face of ambiguity, refuse the temptation to guess.
  • There should be one-- and preferably only one --obvious way to do it.
  • Although that way may not be obvious at first unless you're Dutch.
  • Now is better than never.
  • Although never is often better than right now.
  • If the implementation is hard to explain, it's a bad idea.
  • If the implementation is easy to explain, it may be a good idea.
  • Namespaces are one honking great idea -- let's do more of those!

Best Practice: Use your brain
Don't follow any trend/principle/pattern without thinking about it

Test Driven Development (TDD) makes coders sleep better at night

Just to clarify: Some people seem to think TDD is just an incompetent coder's way of limping from A to B without borking everything up too much, and that if you know what you're doing, that means there is no need for (unit) testing methodologies. That completely misses the point of Test Driven Development. TDD is about three (update: apparently four) things:

  1. Refactoring magic. Having a full set of tests means you can make otherwise insane refactoring stunts, juggling the entire structure of your application without missing even one of the two hundred crazy subtle side effects that result from it. Even the best programmers are reluctant to refactor their core classes and interfaces without good (unit) test coverage, because it's damn near impossible to track down all the little 'ripple effects' it causes without them.

  2. Detecting pitfalls early. If you are writing tests the right way, it means forcing yourself to consider all the fringe cases. Often, this leads to better design choices once the actual development begins, because the coder has already considered some of the trickier situations that may call for a different inheritance structure or a more flexible design pattern. The need for these changes is often not apparent - or intuitive - during initial planning and analysis, but those exact changes can make the application much easier to extend and maintain down the line.

  3. Ensuring that tests get written. TDD requires you to write the tests before writing the code. Sure, that can be a pain in the ass, since writing tests is tedious compared to writing actual code - and often takes longer, too. However, doing so is the only way to make sure the tests will be written at all. If you think you'll remember to write the tests once the code is done, you're almost always wrong.

  4. Forcing you to write better code. Since TDD forces all code to be testable (you don't write code before there is a test for it), it requires you write more decoupled code so that you can test the components in isolation. So TDD forces you to write better code. (Thanks, Esko)

Google before you ask your colleague and interrupt his coding.

Less code is better than more, as long as it makes more sense than lots of code.

Habits of the lazy coder

The first time you are asked to do something, do it (right).

The second time you are asked to do it, make a tool that does it automatically.

And the third time, if the tool doesn't cut it, design a domain specific language for generating more tools.

(not to be taken too seriously)

Be a Catalyst for Change

You can't force change on people. Instead, show them how the future might be and help them participate in creating it.

via The Pragmatic Programmer

Don't Panic When Debugging

Take a deep breath and THINK! about what could be causing the bug.

via The Pragmatic Programmer

You may copy and paste to get it working, but you may not leave it that way.

Duplicated code is an intermediate step, not a final product.

It's Both What You Say and the Way You Say It

There's no point in having great ideas if you don't communicate them effectively.

via The Pragmatic Programmer

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

From: Coding Horror

Build it correct first. Make it fast second.

Frequently conduct code reviews

Code review and consequently refactoring is an ongoing task. Here is a few goodies about code review in my opinion:

  1. It improves code quality.
  2. It helps refactor reusable codes into reusable libraries.
  3. It helps you learn from your fellow developers.
  4. It helps you learn from your mistakes and refresh your memory about a genius code you have written before.

Anything that could affect how the application runs should be treated as code, and that means putting it in version control. Especially build scripts and database schema and data (.sql) files.

Take part in open source development

If you are using open source code in your projects, remember to post your bugfixes and improvements back to the community. It's not a development best practice per se, but it's definitely a programmer mindset to strive for.

Understand the tools you use

Don't use a pattern until you've understood why you're using it; don't use a tool without knowing why; don't rely on your framework or language designer always being right for your situation, but also don't assume they're wrong until proven to be!

Think! About Your Work

Turn off the autopilot and take control. Constantly critique and appraise your work.

via The Pragmatic Programmer

Think of your work as a craft, not as a duty.

Take a step back and look at the whole picture

Every once in a while, you should step back from your code and think about what you are doing in abstract terms. If you don't, you will overlook something that will come back to bite you a few days from now.

I love to dive deep into the code, but from time to time I need to return to the surface and get some air...

Plan First, Design Second, Code Third, Test Always.

  1. Audience - everything we build is for an audience, it'll be used by end users as well as other coders. Ensure it's usable by both.

  2. Simplicity - if you find yourself implementing something complex and convoluted, you're probably missing a more effective, simple solution.

  3. Quality, not perfection - keep your mind on what's important - delivering quality within a timeframe. if you double the estimate, delivering perfection won't save your ass.

If you're stuck, talk about it (even if you only talk to a rubber duck)

Never tell business everything!

Refactoring is part of your job and not something that is up for discussion. If you always add a little "estimated" time to be able to do necessary refactoring there won't be any complaints about it!

Design patterns are your friends

Make sure to keep a copy of the Gang Of Four book lying around somewhere as a reference.

It doesn't have to be art, but it has to be on time

An old rule from journalism that I've had to learn the hard way.

Always build a prototype. Nine times out of ten it will be worth the day/week/month that it takes. Corollary: the length of time spent on a prototype should be proportional to the length/size of the main project.

YAGNI

You Ain't Gonna Need It

Be critical of what you do, AKA think!

Declare everything. Never nest 15 functions into 1 variable.

Instead of being someone who says "I don't know", be someone who says "I want to know". It changes your approach from avoiding/reacting, to proactive discovery and growth.

Red, Green, Refactor!

TDD or Test Driven Development.

  1. Write your tests for the piece of functionality you want to develop, ensuring that they fail since you have yet to write any code.

  2. Write the least amount of code that you need to to make the test pass.

  3. Refactor as needed for things such as efficiency or clarity.

  4. After refactoring, ensure you tests still pass.

This comes from Steve McConnell

"Every new line of code should be single stepped through the debugger"

It is never as easy as you think

This is in response to another answer, but does not contradict it! Both are valuable principles that should be followed.

For databases...

Normalise as far as you can. Then normalise again.

Having a good database (in both structure and data) is critical for making programming less stressful.

Your code should be so simple that anyone who looks at it can understand what it does without reading any documentation.

But don't forget to document everything anyway.

If your API is not braindead-simple to use, there is something wrong with the API. Refactor it until it takes no effort to use correctly.

Before you write any code, research first to find out if the framework already has built-in support or extensible interfaces for what you're trying to do.

Catch bugs early:

  • Use statically typed language so that compiler and static analysis can help you.
  • Unit Test (first or last)
  • Code review
  • Continuous integration
  • Finally, thing that matters the most - Continuous learning.

Understand the intent of the SOLID principles (or any other set of principles or methodology).

Some Things Are Better Done than Described

Don't fall into the specification spiral---at some point you need to start coding.

via The Pragmatic Programmer

Strive to find solutions that require the least amount of code.

Creating software is like.. building a house.

You can try building it without a blueprint, a plan, experience, an architect or qualified tradespeople.

As a result it will almost always cost more, take longer, and be full of future, ongoing surprises that need your time and money.

Just because someone can build a shed without a blueprint doesn't mean they should.

I started a document for my team at my last job, as they had NO programing guidelines, suggestions or anything... It started to get pretty large, but it all made sense.

I'd be happy to share it. But it's not just ONE rule, it was more "Coding Guidelines" than anything else.

Here is a sample outline of what my document contained:

        A.      Source Code
           a.   Formatting
           b.   Variable naming
           c.   Error handling
           d.   Logging
           e.   Text Editor
           f.   Scope Declaration
           g.   Comments / Comment blocks
           h.   Documentation
           i.   API/Library Development standards

       B.       Source Control
          a.    Check-in/Check-out
          b.    Version information
          c.    What belongs in Source Control?

And here is an example from section A.


Source Code

Text Editor:

The choice of text editor is purely up to the developer. Fonts should be mono-spaced, no larger than 18 and no smaller then 8. Although, this is the developers choice, code comments should be present at the top of the source file indicating which editor, font, font size and if applicable indent size should be present. See Comments / Comment Blocks for more information.

Tabs:
Tabs should NEVER be in source files. Tabs should be replaced with spaces, and have an indent of 4.
Line Endings:
Line endings should be in the format CRLF. Most {your company name} source code is on the Windows platform, so line endings should be set to CRLF to be readable on Windows. Line endings should never be mixed in any source file.
Line Length:
Line Length should not extend past 200 chars for most lines. Very long lines of single statement source is acceptable. Function definitions, or function calls should be broken up (and documented). (See API/Library section for more information.)


Of course, this is what worked for US, your MMV, and you'd have to adjust the rules to match your coding styles.

Don't try to make things simpler than they are.

Knowing what you are doing is preferable to unit tests.

Understanding the technology is preferable to test driven development.

Why would you want to waste your life with trial and error methodologies?

"I just can't see how it can fail" is just "It can fail, I just can't see how" with the words rearranged. TEST EVERYTHING!

  1. Understand/walkthrough application code that is good, bad and ugly. You will be better placed at understanding what works and what doesn't.

  2. Talk to people (both IT AND Business) and don't be afraid to ask questions. This works for you in two ways:-

    a) You become more approachable as you seem more human than just that nerd who doesn't speak

    b) Your approach to coding/designing an application is based on real answers - not just on documentation/emails, that could be obsolete.

Always write documentation for your code! In half a year you won't remember about how it works. So don't write any code without documentation!

It's never easy the first time. It will be a snap to do every time after. It's like trying to find a short cut the first time you're driving somewhere. Before GPS.

Code without unit tests is, by definition, broken.

Self-explanatory.

People that know just a little about something (process/software) are the most dangerous people in the world.

Write self-explanatory code (and then still document it), which includes

  • meaningful names avoiding abbreviations and especially consonant clusters
  • functions that are just introduced to make real code read like pseudo-code
  • keeping the level of abstraction constant inside one code unit etc. etc.
Related