Say I have this reasonable contrived situation:

    public class Toast
    {
        public bool Toasted { get; set; }
        public int MinutesToHeat { get; set;}
    }

    public class Toaster
    {
        private Heating _heating;

        public Toaster(Heating heating)
        {
            _heating = heating;
        }

        public void SetHeating()
        {
            List<Toast> toast = new List<Toast>()
            {
                new Toast(){Toasted = true},
                new Toast(){Toasted = false},
                new Toast(){Toasted = false},
            };

            _heating.HeatAgain(toast);
            // or
            _heating.HeatAgain(toast.Where(ts => !ts.Toasted).ToList());
        }
    }

You can implement HeatAgain in a number of different ways:

To filter in the method:

    public class Heating
    {

        public void HeatAgain(List<Toast> args)
        {
            foreach (var toast in args.Where(arg => !arg.Toasted))
            {
                toast.MinutesToHeat += 5;
            }

        }
    }

Or expect a filtered argument:

    public class Heating
    {
        public void HeatAgain(List<Toast> args)
        {
            foreach (var toast in args)
            {
                toast.MinutesToHeat += 5;
            }
        }
     } 

In this case should the responsibility for passing the correct arguments be the responsibility of the caller, callee or both?

I can see that for public facing API, validating all input on the callee side needs to be done, but in the case of internal library and business logic this feels a lot less defined. Filtering on the caller and checking the arguments on the callee would be the safest, but would give a performance penalty, it would also imply that the callee has to know something about the properties of the caller.

What are some good ways of evaluating the optimum balance between the Single Responsibility, performance and validation in cases like this?

Expecting a filtered argument would mean that the knowledge whether or not to reheat an item of toast must reside in the caller. Since the method we're talking about is all about re-heating toast, this makes little sense - knowledge this closely related to the purpose of a method should surely reside within the method rather than with its public API.

The two most important reasons for this are (1) if every caller has to know the condition, the knowledge will be duplicated in several places of the application; (2) by pushing the complexity as far down in the call hierarchy as possible, you create an API with fewer preconditions, which results in reduced complexity for all higher layers - and complexity is the single most important reason why code bases become hard to work with.

The name HeatAgain would suggest that the method would expect the possibility of Toast instances which have already been toasted. Therefore, I would filter it inside HeatAgain directly.

That said, there's no reason for you to have a HeatAgain method. The method should be Bake, and to this method, you would pass the filtered list yourself. If anything Bake would throw an exception if an instance of Toast is given which has already been toasted.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.