When learning game design myself, I made a clone of Geometry Wars, so I've gone through the same issues you're going through with programming.
One way that I was able to limit the amount of projectiles fired from the ship was to create a bullet class that had a static variable 'count.' The static property will allow the value of the variable to persist through all instances of the class.
In the class's constructor, I incremented count and when the bullet was destroyed (either by collision or a time limit) I decremented count.
Then, in the method that would fire the bullets, I just did a quick check against the value of bullet.count and if it was less than the maximum I had defined, allow a new bullet to be created. You'll still need to store each bullet in a list (to iterate through and check collision) but this will give an easy way to keep track of exactly how many are allowed to spawn.
Also,
You could have some sort of list of bullets, and remove them from the list once they've collided with something or gone off-screen.
If you want to limit how quickly you can fire (so you can't fire 3 shots in 0.05 seconds, you might have a timer somewhere (e.g. inside the player).
Decrement the timer with the frame duration every tick, and only allow the player to shoot if the timer isn't already running. Then when you shoot, set the timer running.
You could also have a combination of the two -- you can only have x bullets active at the same time, and they have to be fired with at least y delay.
This is very good advice to set a timer to limit how frequently a bullet is spawned. Otherwise you'll have a bullet spawned every frame, if not every tick, and you'll quickly hit your limit.
E: clarity