No matter how hard we try, over time our programs seem to drown in a tangle of dependencies. Services have shifting responsibilities, new responsibilities keep appearing and the dependency graph keeps growing in complexity. Services end up depending on other services which themselves depend on others, growing in an endless dependency chain which is very hard to break. Changing an interface impacts dependent services throughout the codebase and even with good coverage it can be a scary operation. We rely on advanced injection and mocking frameworks to survive in this growing jungle and still we are struggling. IODA architecture breaks with the traditional view of dependencies in software. It proposes separating logic, integration and data. In IODA architecture style, data flows between functional units which are mutually oblivious of each other. Integration units assemble functional bricks into modules with progressively higher levels of responsibility. Dependencies between functional modules are expressed in terms of data exchanges and no longer in terms of behavior (services calling others). This approach relies on the best of the functional and object worlds: higher-order functions raise the level of abstraction of the program's logic, and reactive flows describe data circulating in the system. Classes are used as integration containers for functional units and to define module boundaries. Even in existing programs and architectures, these techniques can help us from day one in reducing duplication and coupling. Unit testing also becomes easier, with targeted functional tests that resist change.