No matter what the scenario, if a contract is no longer in use it should be terminated. Whether you use expiration dates on your contract or not, it should be terminated.
If you change the status of the contract then it can be filtered out of reports very easily. The status of the contract is key to getting it to report in the right places. i.e. pending, terminated, active, etc. Furthermore, using the termination date and termination code give you more filtering, reporting and view capability. Not always is an expiration date the same as the termination date. So that can be helpful with tracking what happened in those scenarios.
Also using the termination date gives you the ability to filter a list of contracts that were terminated "on or before this date" or however you want to filter it.
The termination code helps you track the trend of why you are loosing contracts or renewing (if you use evergreen), or went out of business, etc. This can also help identify problem areas.
So best practice would be to use all 3 fields. If you set your date and termination code when you click OK on the contract it will automatically change the status to terminated.
If you want to know how many contracts you lost to the competition it's important to use the correct termination codes, more here.
We have ID463 which will alert you of contracts set to expire in a given number of days.