When we started the project which we currently call "Arkency Ecommerce", under the RailsEventStore umbrella - it actually started as an Ordering Management System (OMS), more than actual ecommerce.
I always thought that OMS is an obvious part of ecommerce platforms. Recently I learnt it's not always the case, and even Shopify recommend looking at some other OMS systems as addition to their ecommerce.
Interesting.
Anyway, when our project grew, we were focused on the "Sales Panel" or "OMS panel". The user was probably a sales person. There was no authentication for that. We can assume that it's for internal use of the company hidden in the intranet.
After some time, we have created the "Client View". At first it was without authentication too. We only added a "select list" to choose which client you are "logged in" as.
However, even then, we just used the URL param to remember which client we're logged in as. Also, the functionality was and still is very limited. It was just a list of orders.
There was also a detailed order view, but I just removed it. The reason I removed it, was because it didn't have tests and it didn't use its own read model, just borrowed from the OSM OrdersList read model. It doesn't sound like a big deal, but it actually is. We don't want changes to OSM to interfere with the Client Panel.
One of my recent changes was to extend the authentication with cookies storage, while still not having passwords yet.
I like the concept of tiny steps or as I like to call it "start from the middle".
We started without authentication, but we focused on how it would look like. After "seeing it"/"feeling it", we could decide what next.
That's the luxury of open source codebases, not limited to deadlines and clients.
Small steps allow for two perspectives.
The code perspective
We could start with some code hacks (coupling of read models) and buy some time to think how it should be reflected in the architecture. Only when we feel what smells we can come up with better architecture.
In this case, it was a realisation that the "client panel" is like a separate app. At the application layer it should be reflected in some way. I strongly believe in 2 levels of architectural split in typical web apps.
One level is app layer. The second one is domain layer.
Often people confuse those two and try to merge them. Whatever is the app split, becomes the domain split. This is unfortunate as it's almost not possible to do such one-dimension split.
The UI perspective
Playing with the UI allows to rethink where we are with the features and what are the next stories to implement. Using the UI opens me in thinking what are the next tiny steps to add.
Note that the authentication is not the most important feature of this area. It's crucial once we go live, but before that we can hide it behind a feature flag if we want. We all know how to build authentication. It's not the risky area. But we don't know what to put in the Client Panel exactly for it to be usable. This is more risky.
The current codebase
module Client
class ClientsController < ApplicationController
layout "client_panel"
def index
@clients = ClientOrders::Client.all
render "clients/index"
end
def login
cookies[:client_id] = params[:client_id]
redirect_to client_orders_path
end
def logout
cookies.delete(:client_id)
redirect_to clients_path
end
end
end
module Client
class OrdersController < ApplicationController
layout 'client_panel'
def index
render html: ClientOrders::OrdersList.build(view_context, cookies[:client_id]), layout: true
end
end
end
As you see, it's only setting the cookies, without any user/password checks.
This will be next story to implement, to allow for using passwords for logging in. What's interesting in this "tiny steps" approach is that we can start without even allowing for choosing the password. From the users perspective we can start with the idea of generating the passwords for the client, creating their accounts and only then (later) allowing them to choose/change passwords. That's like 3 other "stories" to implement.
As for the code, some of you may find this bit interesting:
render html: ClientOrders::OrdersList.build(view_context, cookies[:client_id]), layout: true
I went for the Rails view implementation with an unusual approach - writing the templated in Ruby instead of ERB.
But that's a topic for another blogpost.
Thanks!
Top comments (0)