Skip to content

A thought experiment on architecture, object-oriented programming, and composability. #MakeObjectsGreatAgain

License

Notifications You must be signed in to change notification settings

MrHadiSatrio/Journal3

Repository files navigation

Journal3

CI Status Badge Maintainability Rating Reliability Rating

Widgets Reflections Story Moment Editing

Journal3 isn't packed with groundbreaking features; it's just another journaling app. But what sets it apart, at least in my view, is its role as a thought experiment—a space to ponder the "what-ifs."

What if we could build an Android app without leaning on a specific framework, relying on tried-and-true software engineering patterns and object-oriented principles instead?

What if we could bring the power and adaptability of declarative programming into the domain?

What if we started treating objects not just as data containers, but as entities capable of intelligent actions?

Structure

Graph illustrating common components in Journal3 and their relationships.

Each feature (e.g., editing a moment, selecting a place) has a corresponding UseCase class modeling the interactions between the user and the system. These UseCase classes serve as the deepest core and do not return values to the caller.

A UseCase typically depends on an EventSource that exposes a stream of Events. For example, UseCases related to editing may attempt to update the underlying model upon observing a text input event. These Events can originate from user actions like clicks, text inputs, and Back button taps, as well as from the system (e.g., Activity lifecycle changes).

After processing, Events are then sunk into EventSinks. These sinks can be either global or local. Global sinks provide complete observability to the entire domain, enabling functionalities like application-wide logging. Local sinks, on the other hand, may serve scoped functionalities such as finishing the Activity upon receiving terminal events.

The primary role of a UseCase is to act as an orchestrator. For example, if a feature involves persisting a user's change, the UseCase will not know how to perform the action itself. Instead, it will delegate the responsibility to a model. It is then the model's responsibility to actually complete the task at hand.

This same principle applies to presentation. If a feature involves displaying a list of items sourced remotely (e.g., from a web API) to the user, it depends on appropriate models to load the data and render it on the screen.

Highlights

Contributing

Are you interested in joining this journey with me? Feel free to open issues to initiate discussions about anything related to Journal3. I also welcome any kind of pull requests that can help advance this project.

Things to Keep in Mind

  • Journal3 currently relies on several external services such as HERE Maps, OpenAI, and Sentry. If you plan to build the project on your machine, you may need to provide your own keys for these services.
  • Please note that formatting and branch coverage are strictly enforced in the CI pipeline. Ensure that you've run ./gradlew check before submitting a pull request.

License

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

About

A thought experiment on architecture, object-oriented programming, and composability. #MakeObjectsGreatAgain

Topics

Resources

License

Stars

Watchers

Forks