Color Parenthesis

I recommend using the package rainbow-delimiters or similar to show matching parenthesis in the same color. The default color scheme uses so many colors I cannot always see them clearly, so I simplify it like this:
;; Customize rainbow-delimiters to cycle through three colors.
(with-eval-after-load 'rainbow-delimiters
  (setq rainbow-delimiters-max-face-count 3)
  (let ((light ["#6276ba" "cyan2" "#A09183"])
        (dark  ["yellow1" "red3" "sky blue"]))
    (dotimes (depth rainbow-delimiters-max-face-count)
      (face-spec-set
       (intern (format "rainbow-delimiters-depth-%d-face" (1+ depth)))
       `(
         (((class color) (background light)) :foreground ,(elt light depth))
         (((class color) (background dark))  :foreground ,(elt dark  depth))
         )
       'face-defface-spec)
      )))
Adjust colors to taste (and according to the colors available on your system).
If you are curious about the role of the single quote in `(...) and the comma in ,(elt...) in this code, look up "backquote (list substitution)" in the elisp info pages.

Consistent Coding Style

Lisp code can be formatted to taste in terms of where to put newlines. Compare the following styles:

;;  Style 1: "cuddled"
(let ((var1 val1)
      (var2 val2))
  ((exp1)
   (exp2))

;;  Style 2: lines with code have balanced parens
  (let
      (
       (var1 val1)
       (var2 val2)
       )
    (
     (exp1)
     (exp2)
     )
    )
The cuddled style 1 seems to be the most standard for Lisp programming.

Style 2 is similar to the gnu style of formatting {} blocks in C. It wastes screen area with lots of nearly empty lines, but has the advantage of making nicer looking diffs when editing. For example if the (var2 val2) clause in the example above is deleted the cuddled style will show it as a two lines change.

;;  Style 1: "cuddled"
;;  Old version
(let ((var1 val1)
      (var2 val2))
  ((exp1)
   (exp2))
;;
;;  New version; deleted (var2 var1)
(let ((var1 val1))
  ((exp1)
   (exp2))

;; diff --- Two lines changed
1,2c1
< (let ((var1 val1)
<       (var2 val2))
---
> (let ((var1 val1))



;;  Style 2:  lines with code have balanced parens
;;  Old version
  (let
      (
       (var1 val1)
       (var2 val2)
       )
    (
     (exp1)
     (exp2)
     )
    )


;;  New version; deleted (var2 var1)
  (let
      (
       (var1 val1)
       )
    (
     (exp1)
     (exp2)
     )
    )

;; diff --- only one line changed.
4d3
<        (var2 val2)

I prefer an intermediate style in which extra closing parens are put on their own line, especially when there are more than one of them in a row.
;;  Style 3: intermediate
(let ((var1 val1)
      (var2 val2)
      );;  Colored here since an isolated ) looks funny to me in black & white.
  ((exp1)
   (exp2)
   ));  extra closing parens get their own line.
Before I got used to programming in Lisp, I often forgot some parens with the let special form, so for a while I would always add a comment after the paren closing the let form.
(let ((var1 val1)
      (var2 val2)
      ); let
  ((exp1)
   (exp2)
   ))
You may adopt whatever style works best for you. In any event, consistent use of white space (spaces and newlines) may help you avoid or detect mistakes involving too many or two few parenthesis.

Shaking the "parentheses blues"

For many years I was a only a casual lisp programmer, just dabbling with some code to customize emacs a little bit.
During those years I suffered from the "parentheses blues"; not only trouble with unbalanced parens, but also having too few or too many pairs like this:
;; Goldilocks and the three pairs.
;; too few paren pairs ☹
(let (x 7)
     (y 8)
  (+ x y)
  )
;;-->  error: (wrong-type-argument listp 7)

;; too many paren pairs ☹☹
(let ((x 7)
      (y 8)
      )
  (
   (+ x y)
   ))
;;--> error:  (invalid-function (+ x y))

;; Just right
(let ((x 7)
      (y 8)
      )
  (+ x y)
  )
This was rather frustrating. The good news is that the correct number of paren pairs now comes to me naturally 99% of the time.

Why?
1. Practice. I became accustomed to common constructs such as let and cond.
2. Understanding. After some practice writing macros (e.g. until), I now understand how macros (and special forms) which read in variable number of clauses work, and can see the logic behind their syntax.

That being said, I still sometimes feel that all those parens visually clutter code a bit. The following section give some tips for reducing them when using let.

Let there be fewer parens

In Lisp let is very common, as it is the usual way both to create local variables and temporarily overwrite the value of global variables. If you just want to use one variable, and don’t mind if that (or you require that) it is initialized to nil, you can use one fewer pair of parens.
;; Longhand style, case insensitive matching
(let ((case-fold-search nil))
  (string-match-p "cat" "CAT");;  returns nil
  )
;; Shorthand style
(let (case-fold-search)
  (string-match-p "cat" "CAT");;  returns nil
  )
Where case-fold-search which controls whether search commands are case sensitive or not.
(See elisp info pages on "Case Tables" for how to define your own case folding rules, 譬如說你可以安排 {單,単,单}字都可以互相匹配).

If you only need one variable and you want to initialize it with a non-nil value, you might try let1; a simple macro I wrote for that situation.

;; Standard style, case sensitive matching
(let ((case-fold-search t))
  (string-match-p "cat" "CAT");;  returns 0 (start position of the match)
  )

;; Shorthand style using let1
(let1  case-fold-search  t
  (string-match-p "cat" "CAT");;  returns 0 (start position of the match)
  )

;; let1 can do simple error checking as well, since it knows you want to bind *exactly* one variable to a non-nil value.
(let1  case-fold-search;;   Oops, forgot the value.
  (string-match-p "cat" "CAT")
  )
;; --> pops to *Warnings* buffer with warning:
Warning (emacs): let1 warning; attempting to give variable ’case-fold-search’ a nil value or atom body makes no sense
No big deal, just a couple fewer paren pairs to look at.

Troubleshooting

When looking for errors potentially involving unbalanced parens or quotation marks, check-parens is a simple, but very useful command. Just run it the buffer holding the source code of interest.