Difference between revisions of "IS480 Team wiki: 2016T1 IPMAN Midterm Wiki"
Line 223: | Line 223: | ||
The system hashes the order (which is now '''f7e3f23927d8e2921e52aefce5dbf544''') and finds that there is a mismatch in hashes, hence the system will generate a new label for the order. | The system hashes the order (which is now '''f7e3f23927d8e2921e52aefce5dbf544''') and finds that there is a mismatch in hashes, hence the system will generate a new label for the order. | ||
<br/> | <br/> | ||
+ | </div> | ||
+ | |||
+ | <div style="font-family:Garamond;font-size:18px"> | ||
+ | '''Fortnightly Live Deployment''' | ||
+ | </div> | ||
+ | <div style="font-family:Garamond;font-size:16px"> | ||
+ | We scheduled live deployments at the end of every sprint (lasting two weeks), to ensure that our sponsor gets new features and bug fixes frequently. Since we are working alongside with other freelance developers (working on different features) on the same application, it can become complicated to ensure a bug-free deployment. So, communication with our sponsor and the freelance developers as well as handling of the codes must be carefully managed. We have even managed to integrate a task scheduler middleware (celery) on top of the architecture. | ||
+ | </div> | ||
+ | |||
+ | <div style="font-family:Garamond;font-size:18px"> | ||
+ | '''Software Architectural Restructuring''' | ||
+ | </div> | ||
+ | <div style="font-family:Garamond;font-size:16px"> | ||
+ | Codes written by previous freelancers were tightly-coupled and un-reusable. It can be cumbersome to write the same logic at other endpoints. Also, minor changes to codes also frequently broke other features. | ||
+ | <br/><br/> | ||
+ | The diagram below depicts the architecture prior to the introduction of KOPIKaki. | ||
+ | <br/> | ||
+ | [[Image:IPMAN TC MVC Before.png|center|600px]] | ||
+ | <br/> | ||
+ | The code snippet depicts an example whereby the request is used at multiple points which makes it tightly coupled. | ||
+ | <br/> | ||
+ | [[Image:IPMAN TC MVC Before Code.png|center|600px]] | ||
+ | <br/><br/> | ||
+ | To prevent the continuation of these issues, we built a React frontend that makes AJAX calls to RESTful Django endpoints. | ||
+ | <br/> | ||
+ | [[Image:IPMAN TC MVC After.png|center|600px]] | ||
+ | <br/> | ||
+ | These endpoints are modularized and reusable, which allows different ‘views’ to call upon the same endpoints, thereby reducing lines of codes and code maintainability. The decoupling also allows our sponsor to potentially create new views (e.g. iOS, Android) without rewriting backend codes. This can set a good architecture for future freelancers to build upon. | ||
+ | <br/><br/> | ||
+ | Below is an example of how it has been modularized: | ||
+ | [[Image:IPMAN TC MVC After methods.png|center|600px]] | ||
+ | <br/> | ||
+ | To help facilitate this, we are also actively maintaining a set of API documentation that we can hand over. | ||
+ | <br/> | ||
+ | [[Image:IPMAN TC MVC RestEndpoint.png|center|400px]] | ||
+ | <br/> | ||
+ | [[Image:IPMAN TC MVC RestEndpoint orders.png|center|400px]] | ||
</div> | </div> | ||
Revision as of 02:00, 3 October 2016
Project Progress Summary
Note: We have deployed live on Hook Coffee's existing application. However, as Team IPMAN has signed an NDA with Hook Coffee, the above link to the deployed site is only available to existing administrators in Hook Coffee. To view the application, we have created a staging server in which the credentials are available in the deployment section below.
Project Highlights [in chronological order]
- Implementation of Facebook Login, due to unfamiliarity, we took 2 weeks to learn and implement this function in Sprint 3
- Integration with QR code implemented by sponsors so that labels can be pre-populated once code is scanned in Sprint 5
- Conducted our first UAT with our sponsors and packers in Sprint 6 to test our process order and customer management module and worked on Performance and Design Improvements in Sprint 6
- Decision made in Sprint 7 to shift several tasks for subsequent sprints due to greater focus on smart marketing and dashboard graph modules as requested by sponsor. Dropped Facebook bot and recommendation engine (planned for Sprint 12) so that we could spend more time on these two modules.
- Conducted our second UAT with our sponsors and their business development in-charge in Sprint 9 to provide feedback mainly on our smart marketing module
- Integration of Intercom together with our system in Sprint 10
Project Management
Project Status
Access the detailed progress of functionalities here: IPMAN Functionalities Progress List
Project Schedule (Plan vs. Actual)
Several changes were made to the project schedule due to greater emphasis on Smart Marketing module and Dashboard Graph module as requested by sponsors. Hence, IPMAN has dropped several tasks that were scheduled in subsequent sprints to focus on these changes (as reflected in the actual schedule). Progress of the team is well-paced and optimistic.
Planned Project Schedule
Actual Project Schedule
Project Metrics
Project Risks
From the period of Acceptance till Mid-Terms, we will like to highlight that our concerns were 1) Technical Risk and 2) Stakeholder Management Risk as described below:
S/N | Risk Type | Risk Event | Likelihood | Impact Level | Category | Strategy Adopted | Actions |
---|---|---|---|---|---|---|---|
9 | Technical Risk | Team IPMAN was unable to deploy as soon as all the bugs were resolved. Whenever sponsors report for bug issues, team immediately resolves the bugs. However, team IPMAN was unable to deploy the application with the fixed bugs as team was still building on the features in the current sprint and would only deploy the application at the end of the sprint when all features were completed. | High | High | A | Mitigate | Team IPMAN came out with another branch for deployment which means there are now 2 branches, one of it is the deployment branch and another branch is to work on the existing features. Therefore, whenever sponsor raises any bug, team IPMAN would be able to resolve the bugs and deploy immediately without waiting for the features to be completed at the end of the sprint. |
10 | Stakeholder Management Risk | Team IPMAN had to manage not only sponsors but also the developer team that the sponsors engaged. For instance, the freelancer developers have utilized Intercom to track the customers’ interaction on the application. This feature implemented affected the Smart Marketing features that we built. | High | High | A | Mitigate | Team IPMAN communicated with sponsors early and found out more the implementation of Intercom. Team IPMAN also constantly met up with sponsor and checked with him about the progress of Intercom. Team IPMAN followed communication protocol between the sponsors, developer team and team IPMAN. Team IPMAN is using Trello and Telegram for communications and updates. |
Technical Complexity
Use of Adapter Pattern
In order to communicate with Mailchimp services from our web application, we have to make calls to Mailchimp’s RESTful API services. However, we do not want to call these APIs directly from our controller, as it would mean that API calls to fetch similar data would be repeated.
How do we ensure that our main application can reuse the code that calls these RESTful services, as well as protect our main application from changes to Mailchimp’s API?
We solve this by using the Adapter Pattern. The high-level overview is shown below:
Using the above as an example, we delegate the responsibility of calling MailChimp’s RESTful API to the module mailchimp_api.py. In doing so, we can centralize all of the Mailchimp API related code. If Mailchimp decides to change their API interface (e.g. add a new field), only one module will be affected (Adapter – mailchimp_api.py), and we would only have to make changes there. Below is an example of the code from mailchimp_api.py module.
When the actual call is made from the browser to our application, the resulting call graph is as below. As you can see, because all the methods in our app call Mailchimp’s RESTful services through the mailchimp_api.py module, we are able reduce change effort by reducing coupling, and the impacted modules from a change in Mailchimp’s API would only be at mailchimp_api.py. This can be seen from a modified call-graph generated using pycallgraph, as below:
Capturing MailChimp Statistics
Hookcoffee extensively uses email marketing to push out their products. However, while Mailchimp provides the capability to keep track of who has opened the email and who has clicked through, for any given campaign, the activities that the prospective customer has on the website is invisible to the owners.
Mailchimp provides an eCommerce tracking option which enables web developers to record revenue generated from their campaigns, but fail to provide granularity in the sales funnel. For instance, did the customer register their interest on the site? Or did they make a purchase or was engaged in the campaign in a positive way (switching to a different type of coffee).
Previously, it was invisible to HookCoffee what happens at that level. However, by building on top of the eCommerce function, we are able to fetch who the user is and from which campaign he was from by interacting with Mailchimp’s RESTful APIs. We also recorded what the user did AFTER they clicked through the email campaign on the local database.
However, the issue came when we found out that Mailchimp actually stores critical details after the clickthrough on the request itself as parameters on the request, as shown below.
This meant that for every end point, we have to capture these parameters and store them in session, as shown below.
The naïve method is to go into every single url view endpoint and add a method to capture such data, but this proved to be impossible, due to the large number of possible endpoints. Furthermore, as the project went on, we cannot guarantee that all these endpoints will capture the data as other freelancers are also working on the same website.
We used the Decorator pattern to handle this. The decorator is an additional functionality we can add without affecting current implementations. Think of it as a plugin for a web browser.
There exists a plugin to bind decorators to a url.py file, however, there was no indication of how we would do it on the same file. We dig deeper and realize the urls.py is automatically exported as a list in Django. Now, we store all URL patterns as a list of unwrapped (or undecorated) URL patterns. We then hook our own decorator (processMailchimpParams, which takes a request and stores the mailchimp campaign id and resolve the email address if it exists) to the list of unwrapped URL patterns, thereby causing it to execute for every endpoint (with the exception of static pages, e.g. images). This enables an easy to use solution that is easily extensible by other developers on the team, as modifications are made on the same file.
Comparison Using Hashes
HookCoffee is a subscription service that ships out coffee to its users, hence they have to print addresses and labels for each order. However, the generation for these labels/addresses tend to be slow, in the order of minutes (and increases even more as the number of labels grow large). As you can see, the previous system wasn’t designed to handle large number of orders (having multiple print label buttons). So, how do we make it fast?
We experimented with different libraries and found out that the problem was inherent within the pdf generation itself, so we traded space for time, i.e. we chose to generate the labels as soon as they are created, way before the time when the order is process.
For this, we implemented a task scheduler, celery, to create tasks to pregenerate the labels and we deployed the task scheduler on their live server. However, there came another issue: orders can change all the time and there are many different ways that it can change. There are too many endpoints to which the order can be changed (e.g. customer’s name, customer’s address, order details, directly through the database, the Django Admin, etc.). The problem is further exacerbated by foreign key dependencies, so any changes in these tables would have to be reflected in the pregenerated labels. The order table is shown below:
In such a complex situation, how do we ensure the pre-generated labels are up to date?
The solution: Hashing
We convert each order to a String. This string is passed to a hash function, SHA-256, which generates a fixed-length digest which is unique to each order (which is tied to every detail in the order). We are also able to attach relevant metadata as well.
For example, if a customer ordered Guji Liya today, it would produce an order label that is of the file name
Let’s assume Guji Liya is no longer in stock and the packers at HookCoffee hence changed it to NeverEverLand.
The system hashes the order (which is now f7e3f23927d8e2921e52aefce5dbf544) and finds that there is a mismatch in hashes, hence the system will generate a new label for the order.
Fortnightly Live Deployment
We scheduled live deployments at the end of every sprint (lasting two weeks), to ensure that our sponsor gets new features and bug fixes frequently. Since we are working alongside with other freelance developers (working on different features) on the same application, it can become complicated to ensure a bug-free deployment. So, communication with our sponsor and the freelance developers as well as handling of the codes must be carefully managed. We have even managed to integrate a task scheduler middleware (celery) on top of the architecture.
Software Architectural Restructuring
Codes written by previous freelancers were tightly-coupled and un-reusable. It can be cumbersome to write the same logic at other endpoints. Also, minor changes to codes also frequently broke other features.
The diagram below depicts the architecture prior to the introduction of KOPIKaki.
The code snippet depicts an example whereby the request is used at multiple points which makes it tightly coupled.
To prevent the continuation of these issues, we built a React frontend that makes AJAX calls to RESTful Django endpoints.
These endpoints are modularized and reusable, which allows different ‘views’ to call upon the same endpoints, thereby reducing lines of codes and code maintainability. The decoupling also allows our sponsor to potentially create new views (e.g. iOS, Android) without rewriting backend codes. This can set a good architecture for future freelancers to build upon.
Below is an example of how it has been modularized:
To help facilitate this, we are also actively maintaining a set of API documentation that we can hand over.
Quality of Product
Intermediate Deliverables
Topic of Interest | Link |
---|---|
Project Management | Project Schedule |
User Stories | |
Minutes | |
Metrics | |
Risk Management | |
Change Management | |
Project Overview | Project Overview |
Team's Motivation | |
Project Scope | |
Project Documentation | Personas & Scenarios |
Diagrams | |
Technologies Implemented | |
Low & Mid Fidelity Prototypes | |
Testing | Testing Documentation |
Deployment
Note: Facebook login will not work as it is tied to the hostname: hookcoffee.com.sg
To view application, visit: http://128.199.107.26/manager
Username: temp@supertemp.temp
Password: supersecurepassword
Testing
Internal Testing
For easier reference on testing done on our system, the team has came up with this step-by-step process as seen below:
For a more detailed explanation on Team IPMAN's internal testing methodology, view our testing page as linked in the Intermediate Deliverables component.
User Acceptance Test 1 & 2
Team IPMAN has conducted 2 user tests which allowed us to better manage sponsor expectations as well as improve on usability of our application interface.
For more detailed version of Team IPMAN's user acceptance test results, assess here:
Reflection
Team Reflection
This journey has proven to be an enriching learning process for Team IPMAN. We have learnt immensely from one another's strengths and weaknesses and were able to proficiently complement our different working styles.
We have also learnt that communication, compromise and active participation is key to ensure a collaborative learning environment. In addition, together with our generous sponsors who have provided the flexibility and autonomy to work with real data, we have enjoyed working on this project.
Sponsors' Testimonial (Ernest & Faye)
"Team IPMAN produces work of great quality, values constant communication and provides regular updates (every 2 weeks) on the progress of product development. The team is dedicated, possess strong technical capabilities and is willing and flexible with requests to improve the user experience design on the product."
Individual Reflections