Making things easier to read. Here is the example from the contract I wrote:
function unstake(uint256 _cid, uint256 _id) external {
_unstake(msg.sender, _cid, _id);
}
function _unstake(
address _user,
uint256 _cid,
uint256 _id
) internal {
UserInfo storage user = userInfo[_user];
CollectionInfo storage collection = collectionInfo[_cid];
require(
tokenOwners[collection.collectionAddress][_id] == _user,
"Masterdemon._unstake: Sender doesn't owns this token"
);
user.stakedTokens[collection.collectionAddress].removeElement(_id);
if (user.stakedTokens[collection.collectionAddress].length == 0) {
collection.amountOfStakers -= 1;
}
delete tokenOwners[collection.collectionAddress][_id];
user.timeStaked[collection.collectionAddress] = block.timestamp;
user.amountStaked -= 1;
if (user.amountStaked == 0) {
delete userInfo[_user];
}
IERC721(collection.collectionAddress).transferFrom(
address(this),
_user,
_id
);
}
Wrote this way to kinda classify the "frontend, external" function and "backend, internal" function. Makes code easier to read IMHO. Just the way I prefer to write I guess, other than that, I don't see any other reason to split function that way. Perhaps there are some very, very specific cases, but I can't recall any of that ATM.