> When should a function be given an argument vs getting the data itself?

When it has a job besides getting the data.

I can see why you'd be confused about this. None of your functions are named after what they are for. They're named after what you plan to do next. This is a very strange naming style that I don't think is serving you well. It's encouraging you to duplicate code pointlessly.

Consider a style where, rather then telling the caller what to do next, you're telling them what to expect.

```PowerShell
$availableLicenses = Get-AvailableLicenses 
$license = Prompt-Menu $availableLicenses
Grant-License -User $user -License $license
Revoke-License -User $user -License $license
```

Here we see functions so named. They aren't ours but they don't tell us what to do next. Just what we're going to get out of them.

What's missing from your question is anything for your custom function to do. We really need that to be able to properly answer this question.

So let me make up something for it to do. Lets say only members of the dev group should be granted licenses. That way there is some business logic to care about here.

```PowerShell
function GrantLicenseToMember($username, $group, $license) 
{
 $Authorizatized = Get-ADGroupMember -Identity $group | Where-Object {$_.name -eq $Username}
 if ($Authorizatized){ 
 Grant-License -User $username -License $license
 }
}
```

Notice what this function doesn't know. It doesn't know how to get the user. It doesn't know how to get the group. It doesn't know how to get the license. You have to tell it. It's because of that not knowing that it can still be reused as is when any of that changes.

Now something, somewhere, has to know that stuff. Or none of this works.

```PowerShell
function GrantSelectedDevLicense 
{
 $Credentials = Get-Credential
 $Username = $Credentials.UserName
 $group = 'Dev'
 $availableLicenses = Get-AvailableLicenses
 $selection = Prompt-Menu $availableLicenses
 GrantLicenseToMember $Username $group $selection
}
```

This can be called with no arguments. Which means it needed a very particular name because it resolves the dependencies in a very particular way. There can be many such functions that call `GrantLicenseToMember`. Ones that care about different groups. They'll all need different names.

The difference is `GrantSelectedDevLicense` focuses on it's job of knowing where to get all the needed info. `GrantLicenseToMember` focuses on it's job of knowing when to grant and not grant the license.

There is a pattern that describes this separation. It's named [Functional Core Imperative Shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell/). 

By making this separation you are free to keep an area of your code reserved for [pure functions](https://en.wikipedia.org/wiki/Pure_function) that are easy to test and reason about. Functions that are unaware of the world around them and so don't care when it changes. This lets you express your business logic as simply as possible.

It also gives you a business logic free space to dump all the other noise. That noise is not as easy to test. But, without the business logic, it doesn't need much testing.

Fowler was onto a similar idea when he introduced us to the [Humble Object](https://martinfowler.com/bliki/HumbleObject.html).

It all comes at the cost of having to think up these names. Don't do it without a good name. A bad name will make me wish you hadn't created any new functions at all.