Building APIs, Part 3: Controlling Code Complexity
This is a talk I gave for a developer training session recently. This is the third part of the series, but the first two parts are not (yet) posted. The prior two were more interactive sessions; as I adapt them for review, I will post them here.
Part 1 has now been posted.
Building APIs, Part 3: Controlling Code Complexity
The talk is structured around C# examples, but is relevant for most any language. The examples themselves should be trivial to grok for any programmer, regardless of C# experience.
Some external code samples are mentioned; they are provided below.
Code Examples
InputObject and OutputObject
public class InputObject { public List<int> InputSet { get; set; } public int FilterValue { get; set; } } public class OutputObject { public List<int> Result { get; set; } public List<int> BadSet { get; set; } public string FailureReason { get; set; } }
MaybeM
public class MaybeM<T> { public bool HasValue { get; private set; } public T Value { get; private set; } // You can call this "lifting out" the value public MaybeM() { HasValue = false; Value = default(T); } public MaybeM(T value) { HasValue = true; Value = value; } }
MaybeM.Bind
public class MaybeM<T> { public MaybeM<T> Bind(Func<T, MaybeM<T>> function) { if (!HasValue) return this; return function(Value); } }
EitherM
public class EitherM<TSuccess, TFailure> { public bool IsSuccess { get; private set; } public TSuccess Success { get; private set; } public TFailure Failure { get; private set; } public EitherM(TSuccess success) { IsSuccess = true; Success = success; Failure = default(TFailure); } public EitherM(TFailure failure) { IsSuccess = false; Success = default(TSuccess); Failure = failure; } public EitherM<TSuccess, TFailure> Bind(Func<TSuccess, EitherM<TSuccess, TFailure>> function) { if (!IsSuccess) return this; return function(Success); } }
ListM
public class ListM<T> { public List<T> Value { get; private set; } public ListM(List<T> value) { Value = value; } public ListM<T> Bind(Func<T, ListM<T>> function) { // NOT optimized! // Step 1: Generate the intermediate ListM results IEnumerable<ListM<T>> intermediate = Value.Select(function); // Step 2: Collapse the intermediate results into a single List List<T> result = new List<T>(); intermediate.ToList().ForEach(x => result.AddRange(x.Value)); // Return the result wrapped in a ListM, to keep the paradigm intact return new ListM<T>(result); } }
You must be logged in to post a comment.