Last modified 2021-02-11.
Time to read: 8 minutes.
postscollection, categorized under AWS, Azure, Django, Open Source, PostgreSQL, Python, e-commerce, nginx.
In a previous blog post I described how I searched for open source shopping cart and the disappointing software options that I found. These search results showed software projects that began 20 years ago and were generally of low quality. The businesses that manage these projects use a failed business model for open source, namely software-as-a-service (SaaS) without much added value. The hosted products have not changed much since they were first established, and they have not kept up with the relentless advances in computer technology. Those businesses derive some additional revenue from customizing the open-source projects.
I decided to be more rigorous in my needs analysis for a shopping cart with good coupon support, so that I could find more suitable options. I now know that the cart must have:
- Strong discount/coupon support.
- Support for SKUs defined on-the-fly by customers as they interact with the web site.
- Integration with a variety of payment processors.
Before I share my reviews of candidate shopping carts with you, let’s first discuss the state of the e-commerce market, functional and non-functional requirements, the master/detail pattern, and some technology trends for business software.
E-Commerce Is Hot, Hot, Hot
There are a huge number of e-commerce sites, and that market is experiencing strong growth in part due to the COVID-19 epidemic. E-commerce has entered Main Street, as per Geoffrey Moore’s technology adoption lifecycle.
QRA Corp has a good definition of functional requirements. Paraphrasing information from this page:
Functional requirements describe what the system does or must not do, and can be thought of in terms of how the system responds to inputs. Functional requirements usually define if/then behaviors and include calculations, data input, and business processes.
Functional requirements are features that allow the system to function as it was intended. Put another way, if the functional requirements are not met, the system will not work. Functional requirements are product features and focus on user requirements.
Functionally, a shopping cart is well understood, yet in order to be certain that a shopping cart actually works properly, test data and test procedures would need to be designed to verify that all the corner cases were exercised. That would be a significant amount of work to do properly, but at least the work would be rather straightforward.
Non-functional requirements (NFRs)
Non-functional requirements relate to user expectations, and include security, reliability, performance, maintainability, scalability, and usability. Here are some paraphrased excerpts from the Wikipedia article on NFRs:
An NFR is a requirement that specifies criteria that can be used to judge the operation of a system, rather than specific behaviors…
The plan for implementing NFRs is detailed in the system architecture, because they are usually architecturally significant requirements…
Broadly, functional requirements define what a system is supposed to do and NFRs define how a system is supposed to be…
NFRs can be divided into two main categories:
- Execution qualities, such as safety, security and usability, which are observable during operation (at run time).
- Evolution qualities, such as testability, maintainability, extensibility and scalability, which are embodied in the static structure of the system.
I need a shopping cart that has been properly tested, is flexible to configure, and is easy to use. These non-functional requirements are more important to me than the mechanics of how the cart was built or the technology that was used, especially for a proof of concept. In my reviews of shopping cart candidates I will focus on how well they fulfill these NFRs.
I also want to use technology that is current, properly maintained, full-featured and has a future.
Master-Detail Structures, Interfaces and Reporting
Shopping carts are a classic example of a master-detail structure. The user interface of a shopping cart must exploit the master-detail paradigm effectively.
A master–detail relationship is a one-to-many type relationship. Examples of a master-detail relationship are: a set of purchase orders and a set of line items belonging to each purchase order, an expense report with a set of expense line items or a department with a list of employees belonging to it. An application can use this master-detail relationship to enable users to navigate through the purchase order data and see the detail data for line items only related to the master purchase order selected.
In the book SAP BusinessObjects BI 4.0 The Complete Reference 3/E, authors Cindi Howson and Elizabeth Newbould provide this rather abstract definition of master/detail reports:
A master/detail report is a particular kind of report in which a dimension value (master) is used to group data (detail) into separate sections. Master/detail reports allow you to analyze and format data for each unique master data value.
Page 13 of Oracle® Performance Tuning for 10gR2, Second Edition by Gavin JT Powell has a more concrete definition:
First normal form removes repetition by creating one-to-many relationships. Data repeated many times in one entity is removed to a subset entity, which becomes the container for the removed repeating data. Each row in the subset entity will contain a single reference to each row in the original entity. The original entity will then contain only nonduplicated data. This one-to-many relationship is commonly known as a master-detail relationship, where repeating columns are removed to a new entity. The new entity gets a primary key consisting of a composite of the primary key in the master entity and a unique identifier (within each master primary key) on the detail entity.
Master-detail is such a common architectural pattern that most business software vendors provide support for it. Other vendors include IBM, Oracle, Salesforce, and Microsoft. Apple’s iPad is used as a client for master-detail applications so often that the iOS SDK even provides a Master-Detail Application template. The master/detail pattern for Google Android applications can be implemented using the Material Design visual language.
Shopping carts must have engaging and effective implementations for master/detail patterns throughout: in the user interface, in the design of reports, in the data structures, in the types of software modules and their interfaces to each other, and in the internal data flow. The best-known web framework explicitly designed to support the master/detail pattern is Ruby on Rails. Many other web frameworks can support master/detail, of course.
Web servers are usually placed in front of e-commerce servers for scalability and security reasons. Netcraft has been reporting on web server deployments since 1995. The Netcraft January 2021 Web Server Survey shows some interesting trends.
Microsoft’s ASP.NET web framework is free, and web hosting is free (to a point), but those enticements fulfill their purpose by locking in customers to Microsoft's software stack and tools. The nopCommerce e-commerce server is free, very capable, and has enjoyed terrific adoption. This technology might be a good business decision for e-commerce sites that have typical requirements, but not if significant customization or integration with non-Microsoft services becomes important. This article was written by an experienced developer: I rebuilt the same web API using Express, Flask, and ASP.NET. Here’s what I found.
Of all computer languages, Python has arguably the most momentum at present. Ruby on Rails is terrific, but its market share has dropped dramatically since 2011, and without that framework the Ruby language would probably be much less important that it is. Python has been growing in all directions for a very long time. Microsoft’s C# language, which requires a .NET compatible runtime, is also popular, but never had the momentum that Python has.
The following graph compares the popularity of the Python Django library for making web applications against the popularity of the Ruby on Rails framework, for the time period 2009 to the present day. As you can see, in 2011 Ruby on Rails was at its peak popularity; at that time it was 300% more popular than Django. Now the situation is reversed: today Django is 400% more popular than Ruby on Rails.
The one thing about Python that I like better than all other languages is the “batteries included” feature-driven approach. This means that Python projects can aspire to more ambitious goals for a given amount of programmer effort, as compared to implementing with other languages. That was a significant factor in my decision to focus on Python-powered semi-custom shopping carts, instead of investigating shopping carts programmed with other computer languages. Ruby on Rails would doubtless provide an excellent foundation for shopping carts, but I think Python is a better strategic choice for me at the present time in the world of open source.
This is not a decision I would have made in years past. Python's runtime expends a lot of electrical power to run Python programs. As available computing power continues to grow year-on-year within devices everywhere, the “Python runtime tax” has become much easier to bear.
Beyond Open Source
A lot of open source software suffers from limited or no funding. This seriously impacts long-term viabilty. I am happy to consider all appropriate technology, and I am not fixated on open source options. Two major technical components need to be considered:
- E-commerce framework – this dictates the computer language and runtime library.
- Database – the e-commerce framework often dictates the choice of database.
Monolithic vs Serverless Architectures
Modular Yet Monolithic Architectures
Traditionally, software has been built by first constructing functional modules, then combining the modules into a complete program (the monolith). For e-commerce, entire programs are deployed to production by adding configuration information and integrating with external services, such as payment processors. This works well, however, the result is a centralized computing resource that has a fixed capability and resource requirements. The expense of operating the software does not change much, regardless of the traffic volume. In order to handle periods of heavy traffic, complex mechanisms are required to scale up transactional capacity. Conversely, during periods of light traffic, the minimum cost to maintain the system in an operational state can be significant, especially for a startup company.
One of the big architectural advances in recent years has been the introduction of serverless computing. It provides near-infinite scalability without paying for unused resources. CloudFlare has a good definition:
Serverless computing is a method of providing backend services on an as-used basis. A serverless provider allows users to write and deploy code without the hassle of worrying about the underlying infrastructure. A company that gets backend services from a serverless vendor is charged based on their computation and do not have to reserve and pay for a fixed amount of bandwidth or number of servers, as the service is auto-scaling. Note that despite the name serverless, physical servers are still used but developers do not need to be aware of them.
The Serverless Framework is a language- and platform- agnostic framework. Languages supported include Node.js, Python, Java, Go, C#, Ruby, Swift, Kotlin, PHP, Scala, & F#. Platforms supported include Alibaba Cloud, AWS, Microsoft Azure, Fn Project, Google Cloud Platform, Apache OpenWhisk, CloudFlare Workers, Knative, Kubeless, Spotinst and Tencent Cloud. The GitHub project has the code.
Responsive Web Pages
Responsive web pages alter their layout and appearance to suit different screen widths and resolutions. Many of the shopping carts I looked at did not support responsive web pages.
Next: Check Out Django Shopping Carts
OK, so Python, and therefore Django is winning. I admit that I like the Django slogan: “Django – The web framework for perfectionists with deadlines”. When an option dominates the competition, you would need a really special reason to consider other options. My functional and non-functional requirements are mainstream, so I'm going to check out the leading option. Today the leading option is Django. Stay tuned…