why is using delay bad?

I know people try to avoid using delay(). I know that it basically freezes the program until the delay is done.

Does the internal millis() count stop?

If I don't really care about the program freezing every once in a while is there any other reason I should avoid using it sparingly?

Does anyone have a good link that goes into great detail about how the delay function works and how it can affect things?

Does the internal millis() count stop?

No.

The reason not to use delay is if you have to respond to, say, a switch closure, nothing happens until the delay ends.

Sparingly and short is not that bad.

During the delay you can not react on button presses; yes, you can use an interrupt to detect them but in e.g. loop() you still have to wait till the delay is over before you can react on it.

During a long delay you run the risk of a serial buffer overflow and as a result data loss. At 9600 baud transfer of a byte will take a millisecond; there is an internal software buffer of 64 (63?) bytes (size depends on Arduino model). If you delay e.g. 100ms and the sender sends 100 bytes in quick succession without your code being able to read them, you will have lost 30% of the data.

Write your future sketches just using delay().
Within a very short time, you will answer your question.

Hint, try to flash one LED at a 5Hz rate and another LED at a 1Hz rate.

If you don't mind your sketch freezing, then use delay()

Hint 2, write a sketch that toggles an output every 10 days then try doing something else during that time period.
.

...or better still, write a sketch to fade up and fade down the LED on pin 13

FYI, Read this:

If I don't really care about the program freezing every once in a while is there any other reason I should avoid using it sparingly?

As long as you understand that and it doesn't cause a "problem" in your application, it's OK to use delay().

The program doesn't actually "freeze"... But your program is essentially stuck in a do-nothing loop until the delay is over.

There's nothing inherently wrong with delay. If you know up front that your system doesn't need to respond to external events in a timely fashion, by all means use it. The trouble comes when you've done this and then want to enhance it with some functionality which does require responsiveness. Then you're looking at a rewrite.

Since folks can rarely resist tinkering and adding features that they didn't realize that they needed at the start, it's generally safer to eschew delay.

so as a for instance, here is some code to detect soil moisture and add water to soil as needed. the code turns a pump on for 20 seconds, via a relay, as needed:

char wtrSensor = A10;
long wtrDry=430;
long soilMoisture;
const int wtr = 43 ;//make up water relay pin
unsigned long hourDelay=3600000;
unsigned long wtrTimer = millis();
unsigned long currentMillis = millis();
int waterCount=0;

void setup() {

  
  
}

void loop() {
  
unsigned long currentMillis = millis();



if (currentMillis-wtrTimer>=hourDelay){
  soilMoisture = analogRead(wtrSensor);
    if (soilMoisture>=wtrDry)
      {
    waterCount++;
    digitalWrite(wtr,HIGH);
    delay(200000);
    digitalWrite(wtr,LOW);
      }
  currentMillis=wtrTimer;
  }
}//--------------------------end of loop--------------------------

I figure this is a good place to use it. I don't want to add all of the necessary stuff to run the pump on a currentmillis-delay>= setup because I'm starting to realize how many variables my program is going to have once I put the individual pieces together. So using the delay function here and there seems like a good move. I will also have an lcd and button user interface however, and while the pump is running the U/I wont work but it only checks soil moisture every hour and wont run the pump every time so I figure not a big deal. However down the road I want to add a data logger. The pump might interfere with the data logger in a less than desirable way. Does that seem accurate?

That code was hastily written, I'm not sure "char" was the proper variable choice and there may be other problems but I think it demonstrates the basic idea well.

What happens if you want to add manual control?
You will need the UI to be responsive will the pump is on.

Let's say the pump is on and you need to turn it off in case of an emergency.
Your way you need to wait till the delay() times out.

Do things correctly, or don't and reap the beifits!

unsigned long hourDelay=3600000;
delay(200000);
I would make the values stand out by adding UL (others may not)
unsigned long hourDelay=3600000UL;
delay(200000UL);

However, you are attempting to use millis() as in blink without delay then you are adding delay().
Just bite the bullet and learn how to use BWD all the time when timing things.
Become proficient in programming.
Learn how to do things correctly, that way you won't have to come back later asking "why doesn't this work".

There are a many examples on this web site to learn from, here is one example:

//Simple BWD BlinkWithoutDelay examples
//
//Timer variables used
unsigned long currentMillis;
unsigned long pin13Millis;
unsigned long pin12Millis;
unsigned long SwitchMillis;
 
//if these are not changed in the sketch, they can be const
unsigned long debounceMillis = 50UL;  //50ms
unsigned long ledOnTime      = 500UL; //500ms seconds
 
byte lastSwitchState = HIGH;
byte buttonState     = HIGH;
 
//enable/disable flags
boolean flag13 = true;
boolean flag12 = false;
 
const byte Switch = 2; //pushed = LOW
 
//**********************************************************************
 
void setup()
{
  Serial.begin(9600);
 
  digitalWrite(13,LOW);
  pinMode(13, OUTPUT);
  
  digitalWrite(12,LOW);
  pinMode(12, OUTPUT);
 
  pinMode(Switch, INPUT_PULLUP); //pushed = LOW
 
} //  >>>>>>>>>>>>>> E N D  O F  s e t u p ( ) <<<<<<<<<<<<<<<<<
 
void loop()
{
  //save the current time
  currentMillis = millis();
 
  //*************************************
  //Heartbeat LED
  //Toggle LED on and off. Helps show if there is blocking code
  if (flag13 == true && currentMillis - pin13Millis >= ledOnTime)
  {
    pin13Millis = millis();            //re-initialize Timer
    digitalWrite(13,!digitalRead(13)); //toggle LED condition
  }
 
  //*************************************
  if (flag12 == true && currentMillis - pin12Millis >= 5*1000UL)
  {
    //Turn off pin 12
    digitalWrite(12,LOW); //Turn off LED
    flag12 = false;       //disable timing
  }
 
  //*************************************
  //is it time to check the switches?
  if (currentMillis - SwitchMillis >= debounceMillis)
  {
    //code here runs every debounceMillis ms
    SwitchMillis = millis(); //re-initilize Timer
    //go and check the switches
    checkSwitches();   
  }
 
  //*********************************
  //put other non-blocking stuff here
  //*********************************
 
} //  >>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<
 
 
//======================================================================
//                      F U N C T I O N S
//======================================================================
 
 
//****************** c h e c k S w i t c h e s ( ) *********************
//switches are checked every debounceValue milli seconds
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void checkSwitches() 
{
  //re-usable for all the switches 
  boolean thisState;   
 
  //check if this switch has changed state
  thisState = digitalRead(Switch);
  if (thisState != lastSwitchState)
  { 
    //update the switch state
    lastSwitchState = thisState; 
 
    //this switch position has changed so do some stuff
    //"LOW condition code"
    //has switch gone from HIGH to LOW?
    if(thisState == LOW)                         
    {
      //Do some LOW switch stuff here 
      flag12 = true;          //allow timing
      digitalWrite(12, HIGH); //turn on LED
      pin12Millis = millis(); //initialize Timer
    }
 
  } //END of Switch code
 
  //***************************************** 
  // similar code for other switches goes here
  //***************************************** 
 
} //END of checkSwitches()
 
//**********************************************************************
 
//======================================================================
//                      E N D  O F  C O D E
//======================================================================

.