I became infected with functional programming and reactive approach. For inspiration and ideas, I use Haskell and an awesome Rick Hickey article. In the python world I found for myself RxPy and funcy libraries. Now I have thousands of lines of imperative code, which I want to make functional. If everything is simplified, I have an interface of getters and setters for the database and a kernel that works like a state machine. Here's how it looks on pseudo code:
class State(object):
def __init__(id):
self.data = database_interface.get_state(id)
self.status = data['status']
def process(self):
if self.status == 'init':
self.handle_init()
elif self.status == 'request_data':
self.handle_request_data()
elif self.status == 'idle':
self.handle_idle()
# etc...
...
def on_new_message(msg):
id = msg['id']
state = State(id)
state.process()
I have a lot of if
and for
imperative business logic in my state handlers. And I'm really embarrassed how to move from the current model to reactive and functional. Here everything is very simplistic, but who already had a similar experience will understand me. I need advice on where to move next, from ideas to practice, larger than simple utilities or trivial REST api in a functional style. Also, I will be very helped by links to the source codes of really large projects, wherever I could get ideas. Thanks to everyone who responds, having a real experience porting the imperative code to the functional one. Yes, I understand that it will not be porting the code, but rewriting it from scratch. Again, I need examples of projects with a large number of business logic, where there is work with data and mutations of data. Anyway, thank you.
STOP. You have thousands of lines of code in production. It works. It may be a big ball of mud, but it works. I'm a big fan of FP, and write functionalish Python and very functional JavaScript for work myself, but that strikes me as backwards-thinking.
But if you can't resist the siren song of the shiny new thing, start one module at a time. Architecture such that you can't do that? That's a way bigger problem. Refactor to fix that first. Then go through the modules one at a time. If it can be made pure, make it pure. If you are having a hard time making modules pure, refactor them so that you that you have some impure modules and a bunch of pure ones instead of all mixed modules. Note that outwardly pure modules may use side-effects internally, as long as they don't leak beyond the module scope and the caller can't tell the difference that's fine. For now.
Now that you've done that you can change the internal implementation of those modules piecemeal without affecting the rest of the program. Try to replace custom classes with generic data structures where possible, especially at module boundaries. Note that doing so can have a negative impact on perf: profile!
Note that a lot of these tips overlap with what many would consider best practices for defining good object oriented architecture as well (program to interfaces, don't let implementation details leak, KISS, etc.). That is not a coincidence.
Here's another good talk for inspiration. Here's a link to clean architecture of Uncle Bob. Although geared towards UI programming its relevant.
DON'T go read/listen and say "I've got to implement the hexagonal ports-and-adapters pattern with a message queue for IPC or we're doomed!". Again, you have working code. Change it carefully, ideally a bit here and there, respecting what that means (especially to your users).
If all of this seems rather harsh, it's because I've been down this road, and trust me, it hurts. If you don't want to see your new-found enthusiasm vanish in a cloud of bug-reports then tread slowly and softly. I kinda like node.js
but have shot myself in the foot by forever staining its reputation at my employer by doing the kind of thing you're talking about doing. Take heed, spare yourself some pain simply by slowing down.