When you use "DB" you are just defining some data to be stored in RAM at the address "bar" and "bar2" and when the program is assembled, it replaces all references to "bar" and "bar2" with that address in RAM.
When you load data into a register, you can load it such as "ld register, data" or "ld register, (data)".
When it is not in parentheses, you are just loading raw data into the register. Such as, "ld register, 5". When you do something like "ld hl, bar", the assembler replaces "bar" with the memory two-byte address of the string you defined.
When in the parentheses, you are treating "data" as a memory address in RAM and pulling two bytes from that memory address. So if you were to do "ld hl, (bar)" you would be treating bar as a memory address (which it is) and then pulling two bytes from that address.
I always say "two bytes" because the HL register is a two-byte register. It is all one byte if you're using something like the A register (e.g. ld a, (bar) loads 1 byte located at bar).
The _PutS call prints a zero-terminated string located at memory address HL. HL does not hold the value of the string, HL can only hold two bytes of data. HL holds the string's memory address, meaning, it's a pointer to the string.
Essentially, this is what your code is doing:
Code: LD HL,bar2 ;load the two-byte memory address bar2 into HL
LD (bar),HL ;load the two bytes of data from HL into bar
LD HL,bar ;load the memory address bar into HL
BCALL Puts ;Print the string located at the memory address stored in HL (bar)
bar: ;Label this address in memory as "bar"
DB "[Menu]:::::::[D]",0 ;Store some data at memory address bar
bar2: ;Label this address in memory as "bar2"
DB "[#]::::::::::[D]",0 ;store some data at memory address bar2
The third and fourth line will print the string located at bar, but the first two lines is simply taking the memory address of the second string and sticking those two bytes into the first two characters of the string (which I'm guessing is where your "few weird characters" are coming from).
"bar" is, again, a two-byte memory address. It is probably something like $9DA1 and bar2 is probably something like $9DB8. When the assembler compiles your code, it replaces all instances of "bar" and "bar2" with those two-byte values. When you do something like "ld hl, (bar)", you are essentially saying "ld hl, ($9DA1)" which is loading two bytes from that address.
If you want to replace one string with another, I find the ldir operation rather userful.