One of the 'features' of CiviCRM that has been an ongoing source of contention among our customers has been what happens when expired memberships are renewed. The current behaviour is that the existing expired membership has it's end date extended and the start date is altered to reflect the start of the latest membership period. This is great for figuring out when someone first became a member way back when. But, it makes it very hard to see breaks in their membership.
We find some organisations don't want expired relationships to be renewable and recently tackled creating an extension to create a new membership rather than alter an existing one if the end date was being extended. This threw up a few challenges - in particular the hook system really didn't offer the ability to remove or alter the id in the pre hook - in order to prevent the existing membership from being altered. We put in a short-medium term fix via https://issues.civicrm.org/jira/browse/CRM-15749 which will push the problem out for another year but I'm not sure the issue around whether to renew expired memberships can be resolved in an extension.
In terms of fixing this in core the approach I recommend is adding a field 'Is renewable' to the membership status table and allowing that to dictate the behaviour on renewal. My guess is that this is in theory simple but there may be a few places in the code to find and fix to do this. The customer was interested in contributing towards a fix in core (but not fully funding one). I'm certainly interested in hearing if others are interested in collaborating on a fix on this.
Another approach might be to keep existing membership behaviour but make the membership log table work a whole lot hard in terms of displaying history. I'm not sure I see an easy path on that approach though.
The extension is here https://github.com/eileenmcnaughton/nz.co.fuzion.membershiprenewalcontrol - it's not in a 'plug and play' state and at this stage it's not clear which versions of CiviCRM it will work on (we are running CRM-15749 as a patch on 4.4)