3

If I am writing in a functional style and want to use the Replace Conditional with Composition refactoring pattern on a switch or a long chain of if/else if/else if/..., how do I approach it?

I understand with OOP that applying the Replace Conditional with Polymorphism pattern makes this easy as you can simply call a single method and it will already execute the correct code that had previously been in a switch case or a conditional branch in the "less clean" version of the code, based on which subclass you're working with.

But if I'm not using OOP, but FP (which I'm very new to), my initial impression is that the composition pattern may be better suited. Is this The Way, and if so, how is this pattern best applied?

Example pseudocode to apply the pattern to:

if (data.graded !== '') {
  // show letter grade
}
else if (data.start_date === '') {
  // show enrollment deadline date (data.deadline)
}
else if (data.start_date < today) {
  // show "Starts in n days!"
}
else if (data.end_date === today) {
  // show "Course ends TODAY!"
}
else if (data.end_date < today) {
  // show "Course concluded."
}
7
  • Could you explain what this “Replace Conditional with Composition” pattern is? Because I can only find one blog that doesn't provide a useful description. Also, there is nothing wrong with conditionals. The pseudocode looks like actual business logic. It doesn't look like incidental complexity that should be abstracted away.
    – amon
    Commented Jul 10, 2021 at 17:07
  • @amon I believe this is one of Fowler’s refactorings. Problem is time doesn’t work well as a type. Commented Jul 10, 2021 at 17:48
  • @candied_orange That's what I'm asking for clarification – none of Fowler's refactoring patterns are about Composition, which OP is specifically asking about: “the composition pattern may be better suited”. OP is apparently not asking about polymorphism.
    – amon
    Commented Jul 10, 2021 at 18:12
  • @amon - exactly, and functional programming languages typically have precise syntax in the language to handle this: pattern matching, either as an expression, or, more typically, as part of the function definitions.
    – davidbak
    Commented Jul 12, 2021 at 19:31
  • Pattern matching in functional languages is typically not limited to pattern matching on the structure of the data type - though that's where you see most of the examples. Here is an OCaml example of pattern match.
    – davidbak
    Commented Jul 12, 2021 at 19:34

1 Answer 1

3
+50

I would go with a list of functions and another function which combines the results. So you could have something like:

f1(i) => (i.data.graded !== '' ? return i.data.grade : null)
f2(i) => (i.data.start_date === '' ? return data.deadline : null)
f3(i) => (data.start_date < today !== '' ? "Starts in n days" : null)

fComposition(i, funcs) => return funcs.First(f=f(i)!=null)(i);

I think this is equivalent to a composed OOP class where you inject multiple conditional processing classes.

class classComposed
{
    public classComposed(DataProcessor[] processors)
}

You could probably have some clever functional ways of iterating the list depending on how you wanted it to handle multiple hits etc.

4
  • I'm not sure what I'm lookin at here as I'm a FP n00b, so some extra info would be appreciated, but thanks for answering! :) Take my bounty. Commented Jul 15, 2021 at 13:49
  • what language are you using?
    – Ewan
    Commented Jul 15, 2021 at 13:53
  • JavaScript es6 :) . I've read up a bit on currying and compose, so I have some vague idea. But hard to see how to connect the dots. Commented Jul 17, 2021 at 6:42
  • The OP's question appealed to me because most examples of composition show how to do operations on a returned value, not the original value. Eg. Compose(2).add(3). multiply(2) // 10. But I wanted more of an else/if operation as op as shown. Commented Jul 17, 2021 at 6:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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