Design Pattern for implementing erc721

Hello!...
any example to apply some pattern to divide logic and data structures of a contract type erc721?

I have a contract that I am building that is at the limit, (a marketplace with auction)... I would like to have 3 contracts, one for the logic of the marketplace, another for the auction, and the main one on top of these...
question, I've been researching but I don't understand which is the best way to do it.
Whether to use library, or to make 3 contracts and import the 2 in the main one and instantiate them....

Which would be the best way?

this is my contract


pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";

contract Woonkly is ERC721BurnableUpgradeable, AccessControlUpgradeable  {
    using SafeMathUpgradeable for uint256;

    mapping (uint256 => uint256) private _tokens_price;
    mapping (uint256 => address payable) private _auction_vendor;
    mapping (uint256 => address payable) private _offers_marketplace;
    mapping (uint256 => uint256) private _auction_platformCommissionPercent;
    mapping (uint256 => uint256) private _offers_closeTimestamp;
    mapping (uint256 => uint256) private _auction_closeTimestamp;
    mapping (uint256 => address payable) private _auction_bidder;
    mapping (uint256 => uint256) private _auction_amount;
    mapping (uint256 => bool) private _auction_claimed;
    mapping (uint256 => bool) private _auction_exist;

    event AuctionCreated(uint256 indexed  tokenId, uint256 closeTimestamp);
    event AuctionBid(uint256 indexed  tokenId, address indexed bidder, uint256 amount);
    event AuctionClaimed(uint256 indexed  tokenId, address indexed bidder, uint256 amount, uint256 platformCommision);
    event OfferReceived(address indexed payer, uint256 tokenId, uint256 amount);
    event OfferAccepted(address indexed payer, uint256 tokenId);
    event OfferRejected(address indexed payer, uint256 tokenId);
    event OfferExpired(address indexed payer, uint256 tokenId);
    event OfferCancelled(address indexed payer, uint256 tokenId);

    uint256 private constant COMMISSION_EXPONENT = 4;
    address payable private _platformAddress;
    uint256 private _platformCommissionPercent;
    uint256 private _extensionTimePeriod;
    uint256 private _offerExpirationTime;

    modifier tokenExists(uint256 _tokenId) {
        require(_exists(_tokenId), "Woonkly: Id for this token does not exist.");
        _;
    }

    modifier onlyOwner(uint256 _tokenId) {
        require(ownerOf(_tokenId) == msg.sender, "Woonkly: You are not the owner of this token.");
        _;
    }

    modifier offerExist(uint256 _tokenId) {
        require(_offers_marketplace[_tokenId] != address(0), "Kargain: Does not exist any offer for this token.");
        _;
    }

    modifier onlyAdmin() {
        require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Woonkly: Caller is not a admin");
        _;
    }

    function initialize(address payable _platformAddress_, uint256 _platformCommissionPercent_) public initializer {
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        __AccessControl_init();
        _offerExpirationTime = 1 days;
        _platformAddress = _platformAddress_;
        _platformCommissionPercent = _platformCommissionPercent_;
        __ERC721Burnable_init();
        __ERC721_init("Woonkly", "WKY");
    }

    function offerExpirationTime() external view returns (uint256) {
        return _offerExpirationTime;
    }

    function setOfferExpirationTime(uint256 offerExpirationTime_) external onlyAdmin {
        _offerExpirationTime = offerExpirationTime_;
    }

    function platformCommissionPercent() external view returns (uint256) {
        return _platformCommissionPercent;
    }

    function setPlatformCommissionPercent(uint256 platformCommissionPercent_) external onlyAdmin {
        _platformCommissionPercent = platformCommissionPercent_;
    }

    function tokenPrice(uint256 _tokenId) external view tokenExists(_tokenId) returns (uint256) {
        return _tokens_price[_tokenId];
    }

    function setExtensionTimePeriod(uint256 extensionTimePeriod_) external onlyAdmin {
        _extensionTimePeriod = extensionTimePeriod_;
    }

    function extensionTimePeriod() public view returns(uint256){
        return _extensionTimePeriod;
    }

    function setTokenPrice(uint256 _tokenId, uint256 _price) external tokenExists(_tokenId) onlyOwner(_tokenId)
    {
        require(
            _offers_marketplace[_tokenId] == address(0) ||
            _offers_closeTimestamp[_tokenId] < now,
            "Woonkly: An offer is already submitted, token price cannot be changed until it expires."
        );
        _tokens_price[_tokenId] = _price;
    }

    function _refundOffer(uint256 _tokenId) private tokenExists(_tokenId) offerExist(_tokenId) {
        address payable buyer = _offers_marketplace[_tokenId];

        delete _offers_marketplace[_tokenId];
        delete _offers_closeTimestamp[_tokenId];

        buyer.transfer(_tokens_price[_tokenId]);
    }

    function createOffer(uint256 _tokenId) external payable tokenExists(_tokenId)
    {
        require(ownerOf(_tokenId) != msg.sender, "Woonkly: You cannot buy your own token.");
        require(_offers_marketplace[_tokenId] == address(0) && _offers_closeTimestamp[_tokenId] < now, "Woonkly: An offer is already submitted.");
        require(msg.value == _tokens_price[_tokenId], "Woonkly: The offer amount is invalid.");

        _offers_marketplace[_tokenId] = payable(msg.sender);
        _offers_closeTimestamp[_tokenId] = now.add(_offerExpirationTime);
        emit OfferReceived(msg.sender, _tokenId, msg.value);
    }

    function acceptOffer(uint256 _tokenId) external tokenExists(_tokenId) offerExist(_tokenId) onlyOwner(_tokenId) {
        if (_offers_closeTimestamp[_tokenId] < now) {
            delete _offers_marketplace[_tokenId];
            delete _offers_closeTimestamp[_tokenId];
            emit OfferExpired(msg.sender, _tokenId);
            return;
        }
        address payable buyer = _offers_marketplace[_tokenId];

        delete _offers_marketplace[_tokenId];
        delete _offers_closeTimestamp[_tokenId];

        uint256 platformCommission = _tokens_price[_tokenId].mul(_platformCommissionPercent).div(10**COMMISSION_EXPONENT);
        _platformAddress.transfer(platformCommission);

        msg.sender.transfer(_tokens_price[_tokenId].sub(platformCommission));
        safeTransferFrom(msg.sender, buyer, _tokenId);

        emit OfferAccepted(msg.sender, _tokenId);
    }

    function rejectOffer(uint256 _tokenId) external tokenExists(_tokenId) onlyOwner(_tokenId) offerExist(_tokenId) {
        _refundOffer(_tokenId);
        emit OfferRejected(msg.sender, _tokenId);
    }

    function mintFixedPrice(uint256 _tokenId, uint256 _price) external {
        require(!_exists(_tokenId), "Woonkly: Id for this token already exists.");
        require(_price > 0, "Woonkly: Prices must be greater than zero.");
        _mint(msg.sender, _tokenId);
        _tokens_price[_tokenId] = _price;
    }


    function mintAuction(uint256 tokenId, uint256 secondsToClose) external {
        require(!_exists(tokenId), "Woonkly: Id for this token already exists.");
        uint256 closeTimestamp = block.timestamp + secondsToClose;
        _mint(msg.sender, tokenId);
        _auction_vendor[tokenId] = msg.sender;
        _auction_platformCommissionPercent[tokenId] = _platformCommissionPercent;
        _auction_closeTimestamp[tokenId] = closeTimestamp;
        _auction_bidder[tokenId] = payable(address(0));
        _auction_amount[tokenId] = 0;
        _auction_claimed[tokenId] = false;
        _auction_exist[tokenId] = true;

        emit AuctionCreated(tokenId,closeTimestamp);
    }

    function auction(uint256 tokenId, uint256 secondsToClose) external {
        require(!_auction_exist[tokenId], "Woonkly: Auction for this token already exist");
        uint256 closeTimestamp = block.timestamp + secondsToClose;
        _auction_closeTimestamp[tokenId] = closeTimestamp;
        _auction_vendor[tokenId] = msg.sender;
        _auction_platformCommissionPercent[tokenId] = _platformCommissionPercent;
        _auction_bidder[tokenId] = payable(address(0));
        _auction_amount[tokenId] = 0;
        _auction_claimed[tokenId] = false;
        _auction_exist[tokenId] = true;

        emit AuctionCreated(tokenId,closeTimestamp);
    }

    function placeBid(uint256 tokenId) external payable {
        require(_auction_exist[tokenId], "Woonkly: Auction for this token not exist");
        require(!_auction_claimed[tokenId], "Woonkly: Auction was claimed");
        require(_auction_closeTimestamp[tokenId] >= block.timestamp,
            "Woonkly: Auction for this token is closed");
        require(msg.value > _auction_amount[tokenId],
            "Woonkly: Bid should be higher than current");

        uint256 refundAmount = _auction_amount[tokenId];
        address payable refundAddress = _auction_bidder[tokenId];

        _auction_bidder[tokenId] = payable(address(msg.sender));
        _auction_amount[tokenId] = msg.value;

        // Extend close time if it's required
        uint256 bidTimeOffset = _auction_closeTimestamp[tokenId].sub(block.timestamp);
        if (bidTimeOffset < _extensionTimePeriod) {
            _auction_closeTimestamp[tokenId] = _auction_closeTimestamp[tokenId].add(
                _extensionTimePeriod.sub(bidTimeOffset)
            );
        }

        refundAddress.transfer(refundAmount);

        emit AuctionBid(tokenId, msg.sender, msg.value);
    }

    function claimAuction(uint256 tokenId) external onlyOwner(tokenId) {
        require(_auction_exist[tokenId], "Woonkly: Auction not exist");
        require(!_auction_claimed[tokenId], "Woonkly: Auction was claimed");
        require(_auction_closeTimestamp[tokenId] < block.timestamp,
            "Woonkly: Auction is not closed");

        _auction_claimed[tokenId] = true;

        uint256 platformCommission;
        if (_auction_bidder[tokenId] != address(0)){
            platformCommission = _auction_amount[tokenId]
            .mul(_auction_platformCommissionPercent[tokenId])
            .div(10** COMMISSION_EXPONENT);

            safeTransferFrom(address(this), _auction_bidder[tokenId], tokenId);

            _platformAddress.transfer(platformCommission);
            _auction_vendor[tokenId].transfer(
                _auction_amount[tokenId].sub(platformCommission)
            );
         }
        else {
            burn(tokenId);
        }

        emit AuctionClaimed(tokenId, _auction_bidder[tokenId],
            _auction_amount[tokenId], platformCommission);
    }

}


Thanks!

This question was not very clear. Did you hit the contract size limit or what was the issue? If you've found a solution please share with others.