{"id":21669393,"url":"https://github.com/attack-monkey/app-wide-functional-js","last_synced_at":"2026-05-16T21:38:06.228Z","repository":{"id":91873995,"uuid":"147571151","full_name":"attack-monkey/App-Wide-Functional-JS","owner":"attack-monkey","description":"A pragmatic approach to functional javascript in an es6 / node landscape","archived":false,"fork":false,"pushed_at":"2019-03-12T18:07:09.000Z","size":32,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-25T08:44:07.678Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/attack-monkey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-05T19:45:37.000Z","updated_at":"2019-03-12T18:07:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"f69c9e3b-c66a-469d-8952-858e20e31a9f","html_url":"https://github.com/attack-monkey/App-Wide-Functional-JS","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attack-monkey%2FApp-Wide-Functional-JS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attack-monkey%2FApp-Wide-Functional-JS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attack-monkey%2FApp-Wide-Functional-JS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attack-monkey%2FApp-Wide-Functional-JS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/attack-monkey","download_url":"https://codeload.github.com/attack-monkey/App-Wide-Functional-JS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244570357,"owners_count":20474043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-25T12:21:41.730Z","updated_at":"2026-05-16T21:38:06.223Z","avatar_url":"https://github.com/attack-monkey.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# App-Wide-Functional-js\n\nAn application wide approach to functional programming in an es6+ / node landscape\n\nAWF.js provides a set of principles, reasons, and patterns that make functional programming in js simple.\n\n\nPrinciples\n----------\n\n1. State should be stored in one place.\n1. **Immutable** over Mutable.\n1. Use reusable functions over classes.\n1. Functions **where possible should be pure**\n1. Where functions cannot be pure, they should be written with the injector or DI pattern, so they are predictable, testable, and isolated.\n1. Use recursion over looping, and ensure that memory leaks are minimised.\n1. When using Observables and other *function-storing-patterns* ensure that memory leaks are minimised.\n1. Use semantic file names to indicate the type of module eg. `home.function.ts` or the shorter `home.fn.ts`.\n\n\n## Functional vs Object Oriented\n\nThe big difference between a Functional Program and an Object Oriented one is the treatment of state and functions.\n\nIn a functional program state and function is separate...\n\n```javascript\n\nconst state = 0;\n\nfunction increment(state) {\n  return state + 1;\n}\n\n```\n\nIn the above, the function is **stateless**. It has no concept of it's own state, other than that which is passed in.\n\nIn an Object Oriented Program state (properties) and functions (methods) tend to reside on the object. Objects are usually constructed from either classes (es6+), constructor functions (the old school), and factories (Another pattern that also generates objects).\n\n```javascript\n\nstateAndFunction = class {\n  \tconstructor() {\n    \tthis.state = 0;\n    }\n\tincrement() {\n    \tthis.state++;\n    }\n}\n\n```\n\nIn the above, the class creates a **stateful** object. It stores state.\n\n## Why Functional?\n\nState is represented by pure data-objects (no methods).\nThis reduces the need for classes, since objects don't have methods and don't require extending.\nLess classes and extensions means less complexity.\nThere is much less of a need for objects to reference other objects, meaning less errors, and easier tracking of changes to state.\nState changes are immutable ... `e.g. newState = myFunction(state)`, again meaning less errors.\n\n## The Functional Frontend\n\nThe Functional Frontend separates State from Function.\n\nThe function in this case is that which generates the **view** in entirity - let's call it `mainComponent`.\n\nThis could be expressed with something like...\n\n```\n\nconst state = { ... };\n\nconst view = mainComponent(state);\n\ndisplay(view);\n\n```\n\nThe `mainComponent` calls child component functions, passing in `state`. Those components in turn calls the next and so on. \nEach component returns a view, which finally returns the whole view.\n\nOf course our application is not static. Events trigger changes in state, which in turn trigger a change in view.\n\nFunctions that alter state (or produce other side-effects) are generally known as **actions**. \n\nOur application can now be expressed in the following way...\n\n```\n\nconst initialState = { ... };\n\napp(initialState, mainComponent, actions);\n\n```\n\nor even `app({ ... }, mainComponent, actions);`\n\nThere is no `displayView`. Instead `app` runs the `displayView` from within. `app` also manages the functions used to generate the new state. Whenever the state is updated, `app` reruns the `displayView` passing in the new state.\n\nIn the above, `app` is responsible for rendering the components into the view, and also re-rendering the view each time the state changes. Note that `initialState` is passed into `app`, and then `app` immutably manages the state-injection process from there on.\n\n### Example Frontend Frameworks\n\nReact is a good example of a framework that can be used in both a functional AND an OO way.\n\nReact comes with both Functional Components (they don't store state)  \nand  \nClass Components (which do store state)\n\nWhen React is combined with something like React-Fn (Coming soon), it can be used in a completely functional way.\n\nhttps://github.com/jorgebucaran/hyperapp is another example of a Functional Framework - built functional from the ground up.\n\nhttps://maquettejs.org/ is another.\n\n## The Functional Backend\n\nTBA\n\n## Immutability over Mutability\n\nIn functional programming the function should not alter the passed in state, but rather return a new value - **state 2.0**. \nThis keeps things clean as programs become more complex.\n\n*E.g.*\n\n```javascript\n\nconst myNumberV1 = 0;\nconst myNumberV2 = increment(myNumberV1); // 1\nconst myNumberV3 = increment(myNumberV2); // 2\n\n```\n\n\u003e In the above we can see how myNumberV**x** changes over time and if we wanted to, we could print all of the iterations out in a console.log for comparison. This is the benefit of immutability.\n\nWriting immutable functions is easy when dealing with strings and numbers, a little trickier when dealing with arrays, but  much harder when dealing with objects.\n\nUsing [https://github.com/attack-monkey/immutable-update](Immutable Update (AKA iu) ) or [https://github.com/attack-monkey/iu-ts](Immutable Update for Typecript (iu-ts)) simplifies the immutable updating of objects greatly.\n\n## State in one place\n\nAn initial state should be created, representing the entire application state.\nFrom there on, only actions should modify state.\n\n#### Working State\nWhen changing states it may be beneficial to perform several operations on the current state, before actually saving it as the new current state. This is known as *working state*.\n\nEg.\n\n```javascript\n\nconst workingState1 = getCurrentState();\nconst workingState2 = addNewThingToState(workingState1);\nsaveNewCurrentState(workingState2);\n\n```\n\nThis is totally acceptable :smile:\n\n#### Partial State\nIt might also be beneficial to get part of the currentState, perform operations on that smaller **partial state** and then immutably merge it back into a new current state. Again totally acceptable :smile:\n\nReusable functions over classes\n-------------------------------\n\nSince functional programming keeps state and function separate, there are very few times when classes (or constructor functions, factories, etc.) are needed. Classes are great for creating instances of objects that share methods with other objects of the same class. When functions and state are separate though, objects no longer have methods - they are just data.\n\nWhile classes may not be as highly prized in functional programming, reusability still is. If obeying the separate state from function rule, it is easy to make functions reusable.\n\nFor example, in our very first increment function, it doesn't care what number it gets, it simply returns a new number 1 larger than the number passed in. This type of function can be reused throughout the entire app.\n\nPure functions\n--------------\n\nIn a functional program, a pure function exhibits the following characteristics...\n\n- They only refer to paramaters that were passed into the function - no outside variables\n- They don't alter any paramaters that is passed in\n- They always return a value\n- If the same arguments are passed in, the function will always return the same response\n- They don't produce any side-effects (eg. print, send an email, change a global variable, etc.)\n\nFunctions **where possible should be pure** - however their are times when they simply can't be.\n\nActions for example \n\n\nLooping vs Recursion\n----------------------------\n\nA looping function mutates state (eg. i changes state)\n\n```javascript\n\nprogram();\nfunction program() {\n  var i;\n  for (i = 0; i \u003c=10; i++) {\n      console.log(i);\n  } \n}\n\n```\n\nA recursive function doesn't mutate state\n\n```javascript\n\nprogram(0);\nfunction program(state) {\n  if (state \u003c=10) {\n    console.log(state);\n  \tprogram(state + 1);\n  }\n}\n\n```\n\nHowever, if we were to set this to a really high number - we'd blow the memory stack. For every unreturned function call, that function remains in memory and eventually the system will run out.\n\nTo prevent this - make sure that your program is in strict mode and you return a result. This tells garbage collection that the function is no longer required in memory.\n\n```javascript\n\n\"use strict\"\n\nprogram(0);\nfunction program(state) {\n  if (state \u003c=10) {\n    console.log(state);\n  \treturn program(state + 1);\n  } else {\n    return;\n  }\n}\n\n```\n\nObservables and memory leaks\n----------------------------\n\nTODO: Write me\n\nSemantic file names\n-------------------\n\nTo help developers know what type of file they are working on it is best to:\na) limit the number of things that any one file exports to 1.\nand\nb) Semantically name the file based on what the export is\n\nIf it's a singleton, end the file name in .singleton.js\nIf it's a factory -\u003e .factory.js\nIf it's just a function -\u003e .function.js\n\nIf it's multiple of one thing -\u003e .functions.js (Though usually we only want one file to one export)\nIf it's multiple different things being exported -\u003e module.js (Generally not good practice to have a mixed bag, but there may be reasons)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fattack-monkey%2Fapp-wide-functional-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fattack-monkey%2Fapp-wide-functional-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fattack-monkey%2Fapp-wide-functional-js/lists"}