Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Orthogonal Functional Architecture

Well-architected libraries for functional programming are at once immensely beautiful and practical. They are simple but extraordinarily powerful, helping users solve their problems by snapping together Lego-like building blocks, each of which has just one purpose. Yet, there is a surprising dearth of material on how developers can construct their own well-architected functional code. Many functional programming tutorials talk discuss type safety and making illegal states unrepresentable, but few speak on the subject of good functional interface design.
In this presentation, John A. De Goes takes to the stage to discuss a nebulous and underrated tool in the arsenal of every functional programmer. Called *orthogonality*, this tool allows programmers to craft the building blocks of their functional code at "right angles", so so they can be reasoned about simply and composed predictably to solve complex problems. John introduces the concept of orthogonality, looking at its geometric and algebraic origins, presents a way to measure orthogonality, and then walks through a number of interface examples, comparing non-orthogonal designs with orthogonal ones.
By the end of the session, attendees should have a newfound appreciation for how important orthogonality is to constructing good functional interfaces, and they should develop the early stages of an intuition about how to slice up a complex problem into core, single-purpose, composable building blocks.

Related Books

Free with a 30 day trial from Scribd

See all
  • Be the first to comment

Orthogonal Functional Architecture

  1. 1. Orthogonal Functional Architecture Lambda Squared - Knoxville, TN John A. De Goes — @jdegoes http://degoes.net
  2. 2. Introduction
  3. 3. The Dysfunctional Nightmare abandon all hope ye who enter
  4. 4. Procedural Code Ad hoc solutions constructed from large number of non-composable effects that are reasoned about non-locally.
  5. 5. The Functional Dream bliss awaits all ye who enter
  6. 6. Functional Code Principled solutions constructed from a small number of composable building blocks that are reasoned about locally.
  7. 7. Two Keys to Bliss Orthogonality + Composability
  8. 8. Two Keys to Bliss Composability makes functional code powerful, and orthogonality makes it beautiful* *i.e. modular and uncluttered by irrelevant details.
  9. 9. Two Keys to Bliss Composable, orthogonal bases tend to be powerful, but small and simple to reason about, permitting flexible, modular solutions to many problems.
  10. 10. Composability
  11. 11. Composability public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } Is this Java Future composable?
  12. 12. Composability Composability measures the extent to which values can be combined with other values to produce like values
  13. 13. Composability 1 + 1 = 2 Two integers combine to yield another integer. 1 – 1 = 0 Integers are composable with respect to addition/subtraction.
  14. 14. Composability Non-Composable Composable
  15. 15. Composability public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } Is this Java Future composable?
  16. 16. Orthogonality
  17. 17. Orthogonality public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } Is this Java Future orthogonal?
  18. 18. Orthogonality Orthogonality measures the extent to which primitive operations on values have single, unique concerns
  19. 19. Orthogonality Addition moves right Addition/subtraction are orthogonal Subtraction moves left
  20. 20. Orthogonality A A + B B A Non-Orthogonal Orthogonal B
  21. 21. Orthogonality public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } Is this orthogonal?
  22. 22. Orthogonality public interface Future<V> { boolean cancel( boolean mayInterruptIfRunning); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } Is this orthogonal? Timeout Get Timeout + Get
  23. 23. Orthogonality The cardinal sin of non-orthogonality is the tangling of separate concerns, which infects the code base to destroy modularity.
  24. 24. Orthogonality
  25. 25. Process
  26. 26. Steps Toward Orthogonality 1. Make the system composable.
  27. 27. Steps Toward Orthogonality 2. Identify the primitive operations.
  28. 28. Steps Toward Orthogonality 3. Identify the unique concerns.
  29. 29. Steps Toward Orthogonality 4. Refactor the primitive operations until each has a unique concern.
  30. 30. Worked Examples
  31. 31. Worked Examples public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException,ExecutionException, TimeoutException; } Is this orthogonal?
  32. 32. Worked Examples The curse of non-orthogonality! // Would like to write: <A> Future<A> retryUntilSuccess(Future<A> future, Interval spacing) { // ??? } // Forced to write: A retryUntilSuccess(Future<A> future, Interval spacing, long timeout, TimeUnit unit) { // ... }
  33. 33. Worked Examples public interface Future<V> { Future<Tuple2<Future<V>, Function<Boolean, Future<Unit>>>> fork(); V unsafePerformGet() throws InterruptedException, ExecutionException; Future<V> timeout(long timeout, TimeUnit unit); } Future 2.0: Detangle ‘get’ and ‘timeout’
  34. 34. Worked Examples Is this orthogonal? static int compare( String str1, String str2, boolean nullIsLess)
  35. 35. Worked Examples Is this orthogonal? NullIsLess + Comparison NullIsLess Comparison static int compare( String str1, String str2, boolean nullIsLess)
  36. 36. Worked Examples The curse of non-orthogonality! List<String> myAlgorithm(List<String> list, boolean nullIsFirst) { // ... int c = compare(first, second, nullIsFirst); // ... }
  37. 37. enum Ordering { LT, EQ, GT } interface Ord<A> { Ordering compare(A l, A r); } Worked Examples 1. Define a unit of composition
  38. 38. class StringOrd extends Ord<String> { public Ordering compare(String l, String r) { // ... } } Worked Examples 2. Define one dimension (string comparison)
  39. 39. class NullIsLess<A> { private final Ord<A> ord; public NullIsLess(Ord<A> ord) { this.ord = ord; } public Ordering compare(A l, A r) { if (l == null) { if (r == null) return EQ; else return LT; } else if (r == null) return GT; else return ord.compare(l, r); } } Worked Examples 3. Define another dimension (null is first)
  40. 40. List<String> myAlgorithm(List<String> list, Ord<String> ord) { // ... Ordering c = ord.compare(first, second); // <- Beautiful!!! // ... } Ord<String> ord = new NullIsLess<String>(new StringOrd()); List<String> list2 = myAlgorithm(list, ord); Worked Examples 4. Compose orthogonal components
  41. 41. Worked Examples Is this orthogonal?* data MVar a putMVar :: MVar a -> a -> IO () takeMVar :: MVar a -> IO a *Thanks to Fabio the fabulous for this example.
  42. 42. Worked Examples Is this orthogonal? data MVar a putMVar :: MVar a -> a -> IO () takeMVar :: MVar a -> IO a Synchronization + Concurrency Synchronization Concurrency
  43. 43. Worked Examples data IORef a newtype Expect a = Expect a modify :: IORef a -> (a -> a) -> IO Bool data Promise a newPromise :: IO (Promise a, a -> IO ()) awaitPromise :: Promise a -> IO a Synchronization (IORef) Concurrency (Promise)
  44. 44. Worked Examples Is this orthogonal?* *A tiny part of Apache String Utils.
  45. 45. Worked Examples Is this orthogonal? ? ?
  46. 46. Worked Examples Is this orthogonal? data Parser a = Parser (String -> Either String (String, a)) char :: Parser Char fail :: String -> Parser a alt :: Parser a -> Parser a -> Parser a seq :: Parser a -> (a -> Parser b) -> Parser b pure :: a -> Parser a map :: (a -> b) -> Parser a -> Parser b
  47. 47. Worked Examples Is this orthogonal?* data Parser a = Parser (String -> Either String (String, a)) char :: Parser Char fail :: String -> Parser a alt :: Parser a -> Parser a -> Parser a seq :: Parser a -> (a -> Parser b) -> Parser b pure :: a -> Parser a map :: (a -> b) -> Parser a -> Parser b *Trick question — or is it?
  48. 48. Worked Examples Is this orthogonal? data Parser a = Parser (String -> ... char :: Parser Char fail :: String -> Parser a alt :: Parser a -> Parser a -> Parser a seq :: Parser a -> (a -> Parser b) -> Parser b pure :: a -> Parser a map :: (a -> b) -> Parser a -> Parser b SequencingMapping Flattening
  49. 49. Worked Examples Is this orthogonal? data Parser a = Parser (String -> ... char :: Parser Char fail :: String -> Parser a alt :: Parser a -> Parser a -> Parser a join :: Parser (Parser a) -> Parser a pure :: a -> Parser a map :: (a -> b) -> Parser a -> Parser b Mapping Flattening
  50. 50. Wrap
  51. 51. Summary 1. Functional code is composable and orthogonal, allowing a small set of principled building blocks to snap together to solve complex problems in a predictable, reasonable way. 2. Composability measures the combinability of values. 3. Orthogonality measures the singular focus of primitive operations. 4. Refactor to orthogonality to obtain modular clode, uncluttered by irrelevant details.
  52. 52. Thank You! Special thanks to Reid, Cameron, Emily, & the wonderful Knoxville FP community, and the generous sponsor ResultStack! John A. De Goes — @jdegoes http://degoes.net

    Be the first to comment

    Login to see the comments

  • wrapper79

    Mar. 31, 2018
  • PhilDerome

    Mar. 31, 2018
  • pjschwarz

    Mar. 31, 2018
  • FarleyCaesar

    Apr. 1, 2018
  • ecausarano

    Apr. 19, 2018
  • MohdMaqboolAlam

    Aug. 14, 2018
  • bigknife

    Aug. 16, 2018
  • YevgeniKrupetsky

    Nov. 15, 2018
  • MarianoNavas

    Nov. 16, 2018
  • JeroenZuijderhoudt1

    Nov. 17, 2018
  • publicfarley

    Nov. 18, 2018
  • BernardoQuiroga2

    Mar. 15, 2019
  • LenninArriola

    May. 20, 2021

Well-architected libraries for functional programming are at once immensely beautiful and practical. They are simple but extraordinarily powerful, helping users solve their problems by snapping together Lego-like building blocks, each of which has just one purpose. Yet, there is a surprising dearth of material on how developers can construct their own well-architected functional code. Many functional programming tutorials talk discuss type safety and making illegal states unrepresentable, but few speak on the subject of good functional interface design. In this presentation, John A. De Goes takes to the stage to discuss a nebulous and underrated tool in the arsenal of every functional programmer. Called *orthogonality*, this tool allows programmers to craft the building blocks of their functional code at "right angles", so so they can be reasoned about simply and composed predictably to solve complex problems. John introduces the concept of orthogonality, looking at its geometric and algebraic origins, presents a way to measure orthogonality, and then walks through a number of interface examples, comparing non-orthogonal designs with orthogonal ones. By the end of the session, attendees should have a newfound appreciation for how important orthogonality is to constructing good functional interfaces, and they should develop the early stages of an intuition about how to slice up a complex problem into core, single-purpose, composable building blocks.

Views

Total views

4,443

On Slideshare

0

From embeds

0

Number of embeds

917

Actions

Downloads

56

Shares

0

Comments

0

Likes

13

×