Is the idea of ​​the SOLID principle solid or not solid?

In our layered architecture, I am developing a BLL logic component called AppHandover and wrote some basic high-level code for that. I want it to follow the SOLID principles and be loosely coupled, accept separation of concern, and be verifiable.

This is what AppHandover should do

  • Check if the user owns the app. If you do not display an error
  • delete history if possible (i.e. no more apps are assigned to the user)
  • transfer ownership of the next copy

Quesion, I am on the right track and does the following SOLID sample look like?

public interface ITransferOwnership
{
    void TransferOwnership(string userId, string appId, TransferDirection transferDirection);
}
public interface IOwnershipVerification
{
    bool UserOwnsApp(string userId, int budgetId, string appId);
}
public interface IPreserveHistoryCheck
{
    bool ShouldDeleteTemporaryBudgetData(string userId, int budgetId);   
}
public interface IRemoveHistory
{
    void DeleteTemporaryBudgetData(string userId, int budgetId);
}

      

Executing the handover process

public class AppHandoverProcess : KonstruktDbContext, ITransferOwnership
{
    private IOwnershipVerification _ownerShipVerification;
    private IPreserveHistoryCheck _preserveHistory;
    private IRemoveHistory _removeHistory;
    private ITransferOwnerShip _transferOwnership;

    public AppHandoverProcess()
    {

    }
    public AppHandoverProcess(IOwnershipVerification ownerShipVerification, 
        IPreserveHistoryCheck preserveHistory, 
        IRemoveHistory removeHistory)
    {
        _ownerShipVerification = ownerShipVerification;
        _preserveHistory = preserveHistory;
        _removeHistory = removeHistory;
    }

    public void PerformAppHandover(string userId, string appId, int budgetId)
    {
        if (_ownerShipVerification.UserOwnsApp(userId,budgetId,appId)) {
            if (_preserveHistory.ShouldDeleteTemporaryBudgetData(userId, budgetId))
            {
                _removeHistory.DeleteTemporaryBudgetData(userId, budgetId);
            }

            //handover logic here..

            _transferOwnership.TransferOwnership(userId, appId, TransferDirection.Forward);
        }
        else
        {
            throw new Exception("AppHandover: User does not own app, data cannot be handed over");
        }
    }
}

      

+3


source to share


2 answers


With regard to the code you described above, I definitely think you are on the right track. I would nudge the design a bit and define TransferOwnership as an optional interface.

Following this approach, your AppHandoverProcess is completely decoupled from it by the client and the behavior will be defined in the service configuration.

Providing isolation for TransferOwnership will allow you to easily execute UnitTest on any object that implements the interface without having to mock the AppHandoverProcess dependency.



Also any AppHandoverProcess test should be trivial as the only thing you need is to make sure your services are being called or that an exception is thrown.

Hope this makes sense,

Sincerely.

+4


source


I would make KonstruktDbContext as an injectable dependency. The AppHandover process should not inherit from it as it seems to be a different responsibility.



+1


source







All Articles