Category Archives: Sprint 6

Sprint Retrospective – 2 May 2018

As the final full sprint comes to a close, I find myself wishing for just a bit more time to work. With the testing issues resolved, we were able to work much better than we have in the past, and with a newfound grasp of the technologies at hand. Had we begun the semester with this kind of understanding of what we were working with, I think we would have had a vastly different product than what we currently do. During this sprint, we corrected what was left of the sync/async issues we were having, made a switch over to a singleton pattern for our service (with a bizarre development), and got as much of the service in minimum working order as we were able.

Having redone the tests to be compatible with Promise objects, I spent the first bit of the sprint trying to convert the offline storage service into a singleton pattern. The primary difficulty in this turned out to be that Ampath had its own tslint.json file for enforcing the organization’s style guide. When coupled with the fact that WebStorm regards conflicts with the tslint file in the same way it regards syntax errors, it meant that the code wouldn’t compile, and I had no clue what was wrong with it. Only after reordering my field and static method declarations would the tslint stop holding my code hostage. After going through this whole ordeal, I think it would be nice if at the start of future semesters, Ampath provided capstone sections with a style guide to avoid headaches like this one. After the conversion to singleton, I moved to the tests to rewrite them to interact with the singleton object. In the middle of this process, however, something very non-intuitive and very obnoxious became visible.

First, a recap of the purpose of Singleton Pattern: by making the default constructor for a class private, one can disable willful instantiation of that class. Then, a static method which returns the single instance of the class allowed to exist is written. With this structure, you can guarantee that only one instance of a class exists, and there is an easily available mechanism to grab a reference to that class.

“Not in my house,” says Angular. It turns out that making the default constructor private doesn’t actually give it any kind of private visibility; you can still instantiate the class with “new.” I only realized this when halfway through writing my test cases, I accidentally wrote “= new OfflineStorageService();” and was not told that it was a problem. Rather, the tests all ran and passed, even though – and I triple checked myself on this one – the default constructor in OfflineStorageService was most definitely declared private. I shared this information with my group at the next meeting, and we each agreed that it was one of the most baffling things we’d ever seen in programming.

In spite of my shock, things proceeded smoothly and steadily for the rest of the sprint. Our communication was spot-on, as we were giving each other daily, sometimes hourly updates in our group text message. The code, while sometimes strange and alien, was actually starting to behave like we wanted it to behave. We were in consistent communication with one of the other groups, and occasionally communicating with the other two. Really, this felt like a culmination of what we’d learned from the last five sprints – as it ought to have. Perhaps we could have done something better; I probably could’ve been better about standup meetings and asking questions about Ampath, but I think in general, each of us feels far more comfortable with this entire process. With only the documentation left to do, along with our final presentation, I think I can say I’m beginning to feel what it means to be this thing called a “software developer.”

From the blog CS@Worcester – Studio H by Connor V. and used with permission of the author. All other rights reserved by the author.

Sprint Retrospective 6

During Sprint Retrospective 6 I continued to learn more about the CryptoJS library, encryption, Angular, and Git. From the CryptoJS npm page, this code snippet helped me understand how data is encrypted and decrypted using the CryptoJS library:

var CryptoJS = require("crypto-js");
 
var data = [{id: 1}, {id: 2}]
 
// Encrypt
var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123');
 
// Decrypt
var bytes  = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123');
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
 
console.log(decryptedData);

My job on the team was to implement a function to encrypt a data record, I also added the decryption function as they go hand-in-hand. The example shown above is in Javascript but easily implemented them into a Typescript file. The following are the functions I came up with in my encryption / decryption service file:

Encrypt a Record


public encryptRecord(data: any[], privateKey: string) : string{
    let ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), privateKey);
    return ciphertext;
}

This function takes a set of data, and a given private key, encrypts the data, and returns and the encrypted string.

Decrypt a Record


public decryptRecord(ciphertext: string, privateKey: string) : string{
    let bytes  = CryptoJS.AES.decrypt(ciphertext.toString(), privateKey);
    let decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
    return decryptedData;
}

This function takes the encrypted string, and a private key and returns the decrypted string.

I learned a lot of information about Typescript and web applications, I learned more about Node.js, encryption, and Javascript. I feel this information will help me in my professional career, especially if I am working with web development and API’s. I am interesting in further contributing to this open source project, and possibly more. I would like to improve my skills in Javascript and Angular. I would like to learn more about Angular testing and continue to work on the tests I wrote for my functions, to make sure they are working properly.

The team was successful in finding a suitable cryptography library that had all the features we were looking for, but we did run into trouble getting CryptoJS implemented in the ampath application. I successfully implemented the features for encrypting and decrypting a data record, hopefully it will be used to help future teams encrypt patient data. I think I spent too much time researching and not enough time actually working with the ampath application. I did find though that the solution I needed was easier that I thought it would be. We all hit some roadblocks getting things to always work, sometimes the ampath application would give us compilation errors out of nowhere.

During this Sprint we continued working on our respective parts of the encryption service. I successfully wrote two functions, one to encrypt a data record and one to decrypt a data record. I wrote test files for the functions that I believe will work but had some trouble getting the tests to work. Once we made the decision to use CryptoJS, I used this source to help me contribute my part to the project. I pushed my part of the project to my local repository and then made a pull request for the group repository. I did have some trouble with Git dealing with merge conflicts and setting the remote, but feel I was due for a refresher and eventually solved my problems.

The post Sprint Retrospective 6 appeared first on code friendly.

From the blog CS@Worcester – code friendly by erik and used with permission of the author. All other rights reserved by the author.

Sprint 6 Retrospective

This was our final full sprint, the next one being only a couple days, and designed for gathering our thoughts, doing a pseudo post mortem, and presenting what we learned through the project. With it, we have essentially finished the project. This last sprint was mostly dedicated to a final breakthrough on on our service and the use of Promises.

In the beginning of the sprint, it was filled with some level of frustration. Our team lacked extensive or comprehensive knowledge on Promises, and asynchronous coding in general. This led to some blind trial and error attempts at trying to get our service to work correctly. The main issue was that our tests were failing in ways that were confusing. The main way being that the code in our service functions were seemingly being skipped, not happening at all, or just not returning what was expected or wanted.

Due to this, it was hard to tell where we were going wrong. Because of this, we eventually began researching Promises more to discover what the issue was. Eventually in one of our bi weekly, in person meetings it was brought to my attention by Shane Rookey, a team mate, that the issue was not that were doing something wrong in our functions. The main issue was the way were testing them.

With a promise, due to it being asynchronous, it is unknown when it is resolved. That’s why you use the ‘.then’ method of a promise. This method executes a function when the promise resolves, or when it fails. When the promise resolves, then do this, essentially. We would use PouchDB’s methods (.get, .put, etc), handle it in a .then, and then attempt to return the response of those methods. And then in our tests we would use a simple line of code to see if the response was what we expected.

However, because what was being returned from the methods was a promise, doing anything with it without using .then just does not work. We were simply using a line of code that expected the responses from the methods to have a field called ‘ok’ to be true. But that is a regular synchronous line of code. It has to be placed in the .then to work. Anything done with a promise has to be done in a .then. And attempting to return it also does not work, as after something is done in a .then, it returns another promise.

You can not just write the functions in the service asynchronously and then just go on as normal when handling them in tests and other services or code. That was what we did not understand. Once that was understood, writing tests and actually seeing if our functions, well, functioned, was much easier. Another team by this point had managed to get a service running that would take patient data and store it using PouchDB. We both met during the sprint and decided we should focus on getting tests running for the service while they focused on getting a GUI to display stored data up and running.

In the end, I felt more could have been done if we had some more prior knowledge. And also, if there was a bit more of a comprehensive guide on using promises and how to work with them. Some more comprehensive documentation would have smoothed things out. Our team will strive to document all these things for future developers that work on the project, which will hopefully aid in alleviating a lot of frustration.

From the blog CS@Worcester – Fu's Faulty Functions by fymeri and used with permission of the author. All other rights reserved by the author.

Sprint #6 Retrospective

During this Sprint, my team and I tried to complete as much as we could since we are coming to an end in the semester. We wanted to at least give JJ and the AMPATH people some sort of workable interface for our offline data capture service. Throughout the process of finishing and having a workable interface, the team and I decided to focus all of our attention on that aspect, aside from the encryption service that I was trying to discuss with the encryption team involving the javascript implementation crypto.js.

Some tasks that we did during the week that helped lead us to establishing the offline data capture service interface were:

  • Help ensure GUI code is compatible with any offline-capturing abilities we implement when the user is online and vice versa.
  • Create balsamiq diagrams outlining current and anticipated implementations of offline-capturing the OpenMRS / ETL data.
  • Ensure all new components, GUIs, etc comply with basic AMPATH CSS styles, overall look and coding convention.
  • Code the offline GUI based on the help and input from Jerry and other teammates.
  • Write/maintain tests for our implementations so they are always as current as possible.
  • Seek help from the AMPATH development team if any of us hit a roadblock concerning implementation.
  • Offer suggestions to other teams based on our overall process, so that all teams’ implementations can work together as smoothly as possible.
  • Touch base with all teams (encryption, offline-storage, and login) regarding their overall progress.
  • Develop high-level idea of a Doctor/Provider object so we can consider if it is worth implementation.
  • Develop mock diagram where a “Doctor/Provider” can pick and choose what patients to sync.

The above tasks were what was tried and attempted. What was done and completed were the establishment of the Doctor/Provider object, and the mock diagram. For the GUI task, we had to communicate with JJ a lot. Due to the amount of time the team had, we had a feeling that there wouldn’t be enough time to create a perfect GUI, even though JJ wanted one. Midway through the sprint, we sent JJ our progress on what we did so far for the offline data capture service through a walk-through video that we shared on the slack channel. JJ then understood where were at with the progress and we concluded that it was okay to work towards establishing an interface where the user can clearly see if he is offline/online along with the data. That was one of the tasks that we had approach differently and adjusted to.

As a team, we learned to make a major adjustment to our task during this sprint. We knew that time was a concern, and what the people at AMPATH and JJ were expecting to get, which was the new offline GUI, seemed to be too much. We wanted to at least deliver something to them that at least worked, which is why we moved away from creating the new GUI. From this situation, this could be applied in real life software development environments because there will come times where I would have to adjust my tasks to deliver something that the customer wants, even if it isn’t 100% of what they want it to be, it will perform the same functions of what they want it to do.

The team’s performance during this sprint was above above average. Everyone contributed evenly or more than an adequate effort throughout this sprint. Communication was very effective between each member and between our team and AMPATH. As an individual, I performed average during this sprint. I mainly tried to talk to the other teams, trying to get some info on their status. The only team that we communicated to more than others was the offline data storage team, and we began to work alongside with them since our tasks were similar to theirs. I also tried to help find several components in the AMPATH code for which JJ wanted the interface to display such such as genral patient data, vitals, lab results, and HIV summaries.

Overall, the team worked diligently and we wouldn’t have proceeded in any other way. We will try to have our offline interface working, completed and delivered hopefully by the end of this next half sprint.

From the blog CS@Worcester – Ricky Phan by Ricky Phan CS Worcester and used with permission of the author. All other rights reserved by the author.

Sprint Retrospective 6

This sprint, we managed to get multiple changes merged into our team’s offline-login branch. Luigi and I worked on coding the back end of the checkbox with George’s help. In the authentication service, Luigi created two new methods, authenticateAndSave and setAndSaveCredentials. These mirror the authenticate method and the setCredentials method respectively, each with an added boolean parameter. We decided this would be simpler than trying to restructure the existing methods to accept a boolean value they would only use sometimes. The authenticateAndSave method saves the boolean value in the saveOfflineCreds variable and then passes other duties to the authenticate method, and setAndSaveCredentials stores the user in localStorage and then passes other duties to the setCredentials method.

For my part, I tried to modify the login component to utilize authenticateAndSave instead of authenticate when the checkbox is checked. Attempting to make this change produced a lot of unexpected difficulties. Using the HTML checkbox’s id attribute, I declared a variable to perform the .checked method on, which defaulted to the type HTMLElement. Trying to call .checked on this object didn’t work, so I tried to cast it to an HTMLInputElement, the type that has this method, in the declaration. When this wasn’t allowed by the TSLint file, I used “as” syntax type assertion. This was accepted without compiler errors, and I could call .checked on the HTMLInputElement object, but we found later that the code testing whether the checkbox is checked broke the ability to log in. When you click the login button, the login method gets to the conditional statement that checks whether the checkbox is checked and can’t go past it, giving a type error that says “Cannot read property ‘checked’ of null.” We weren’t able to fix this by the end of this sprint, but we plan on it being the final change we make before the semester ends. Once we can verify that the authenticateAndSave method is called correctly, the back end will be complete and users will have the option to store their credentials for offline use later.

Members of our team also made edits to the online tracker component, wrote tests for the checkbox functionality, and documented the progress we’ve made so far so that whoever continues the work after us can better understand our choices.

I thought our teamwork was excellent this sprint too. George identified to Luigi and I the parts of the code he’d written which in conjunction stored the user credentials in localStorage. Luigi and I were able to complete separate parts of the checkbox back end task and then integrate them.

I definitely could have benefited from a more in-depth knowledge of HTML and JavaScript this sprint. Following this course, I plan to set aside some time to dive deeper into these and CSS, so that in the future I won’t get blindsided by problems like the one I’m facing trying to get my checkbox element recognized as the appropriate type. I do feel like my skills are steadily improving and that this course has aided that. I look forward to having more opportunities to grow as I begin my career.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

Sprint Retrospective Blog 6

During this sprint, we continued to work on revising and testing our methods that we created. At first, I was responsible for creating the update method as stated in my last blog. I found the PouchDB API to be extremely helpful for this as it essentially gave me what I needed to create the update method. However, we realized that we could save lines of code by having the add method update the data if it already exists. This made more sense so I started working on the getDoc method. Here is a screenshot of the code I wrote:

getdoc

This code is simple enough, but it was the tests that I struggles with through this sprint:

getdoctest

Even though I failed to get this test to pass *correctly* (it passed but gave errors in the karma console and didn’t work the way I expected), I discovered that I became a lot more comfortable talking about javascript and typescript. Before this class, I did not have any experience learning anything about the angular2 framework and nothing about javascript and typescript. After this weeks sprint, if we had more time I would dive deeper into promises and how to handle them correctly in test suites (it is more complicated than I would think). I would also dive deeper into javascript/typescript since that was the majority of what we used to put this code together.

Our team is still working well together, however I have noticed a slacking in communication between each other. This is only normal as the semester is coming to an end and people are getting ready for finals and presentations and what not. If our team could proceed differently, I think that they would all agree that we were really close to figuring out the solution to our problems. Working with other teams and investigating the code they wrote helped us get another perspective of the code that we wrote. If we had more time we would also clean our code to make it much more readable with clear comments. For example, since we didn’t have the time to learn the correct coding etiquette our add method ended up looking like this (the thens and catches are all promises, which I am sure we could have done differently):

admethod code

However, even though this code looks really messy and complex, it works and the test passes. One thing that helped our team progress through our struggles was using console.log outputs to see where the code would reach before failing. This was a very useful tactic for us. Another useful tip that helped us get through was the console on the karma testing screen. This had much more information about what was going wrong in our code than the webstorm terminal offered. Webstorm automatically opens the karma browser, you can press “CTRL+SHIFT+I” to bring up this window with the elements, console, source, network and more. You can also view and delete the database that you have created. This proved to be helpful for ensuring that our add method worked even when the tests didn’t.  Here is a screenshot:

karmaconsolescreeen

This screenshot sums up all of our troubles. In the webstorm terminal the test “passes” but when you open up the console here you can see how many errors it has generated.

After all of this we learned that a better way of going about testing would be to test that our methods are calling pouchDB’s method in the correct order at the correct time. We may have dove a little too deep into specifically testing every little detail about our own methods that it was extremely inefficient. We would definitely change the way we tested our code as it would have saved us some time and headaches.

From the blog CS@Worcester – Rookey Mistake by Shane Rookey and used with permission of the author. All other rights reserved by the author.

Sprint 6 Retrospective: Capturing and Displaying Specific Categories

We’ve just completed our final working sprint, consisting of six primary objectives.

1.  Maintain communication and collaboration with all other teams.
2.  Create a mock diagram demonstrating our implementation ideas.
3.  Capture the specific data requested by the AMPATH team.
4.  Store this specific data into the PouchDB database.
5.  Write tests for our existing code.
6.  Develop an offline GUI to display specific offline data.


Maintaining communication and collaboration:

Sprint 6 involved substantial communication between ourselves and the other teams. Since this was our last working sprint, our team knew it was imperative to keep up to date on what everyone is working on. Each team is working on a critical part of the offline AMPATH implementation. I like to think of these critical parts as pieces to a puzzle. Eventually we’re all going to have to put these pieces together, and they all have to fit right. Our team agreed that communication is the best way to ensure how the pieces will fit in our final stages of implementation.

Based on our cross-team discussions during this sprint, we began brainstorming how to connect all teams’ implementations as a whole. We’re in the process of designing a mock-up that demonstrates the idea. This ought to be done in time for our final presentation next week.

Creating a mock-up demonstrating our implementation ideas:

We felt that designing a mock diagram was important for the AMPATH team (and our classmates) to see exactly what we envision our final implementation to look like.

Offline Component GUI

We would like to give credit to the offline-storage team for designing the original mock-up above. Small changes were made to reflect the specific information we plan on capturing. After receiving approval from JJ, we began working to implement this overall design.

Capturing the specific data requested by the AMPATH team:

This refers to capturing five specific categories of information to be stored in a PouchDB database:

1. Basic Patient Information
2. Patient Visits
3. Vitals
4. Lab Results
5. HIV Summary

We were able to accomplish updating our offline-data-capture component to include functions that capture the aforementioned data. We were able to accomplish this by using existing OpenMRS services located within the AMPATH app. We made functions where each focuses on capturing and storing one specific category.

Storing the aforementioned categories into PouchDB:

The AMPATH team suggested that we separate the different categories when storing them into PouchDB. This makes a lot of sense; we noticed the original data we were capturing tended to exceed over 3000 lines per patient. The larger the file, the longer it takes to load. We want our offline implementation to load as quickly as possible for the convenience of those using it.

Now that we’re only capturing specific data and storing each category separate, the file sizes are significantly smaller. We opted to store them by name of the category, followed by a given patient’s UUID. For example:

patient-064e419c-ff4e-4a6f-b83f-e1df48e80723
vitals-064e419c-ff4e-4a6f-b83f-e1df48e80723
visits-064e419c-ff4e-4a6f-b83f-e1df48e80723
labs-064e419c-ff4e-4a6f-b83f-e1df48e80723
hivSummary-064e419c-ff4e-4a6f-b83f-e1df48e80723

Writing tests for our existing code:

Ideally, we should have written our tests prior to any actual implementation. Then we could have written our code in a specific fashion to make our tests pass. I am still new to unit testing; this is something I need to work on in future projects (writing tests before implementation). On a positive note, the offline-storage team has made substantial progress writing tests for their component and service. Since they’re using PouchDB as well, our team should be able to easily revise their tests to suit our needs.

Developing a GUI to display specific offline data:

This concerns designing a component with the overall look of the aforementioned mock-up we came up with. We are in the process of implementing this GUI, but we’re having issues getting anything to display to the user. Everything I’ve tried so far hasn’t been working, and it’s pretty frustrating. Here’s the type of errors I am getting:

trying-to-display-pouchdb-data

I think it has something to do with losing the result once leaving the promise. I am hoping to get this working by our project presentation. If anyone wants to see my most recent attempt at getting this working, the commit can be found here.

Overall

I think this was a very eventful sprint. We’ve all done a good job communicating not only with each other, but with other teams as well. Personally, I believe many of my contributions would not have been possible without the communication and support from my teammates, AMPATH, the other teams, and my professor.

 

From the blog CS@Worcester – Jason Knowles by Jason Knowles and used with permission of the author. All other rights reserved by the author.