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.

Sprint Retrospective 5

This sprint was productive despite lots of small impediments along the way. My main task was to implement the front end of the checkbox we’ll be using to decide whether a user’s credentials will be stored when they log in. I managed to complete this and submit a pull request which got merged by Wednesday.

Problems building the app stopped me from making much progress in the beginning. At first it would just take a very long time, but after pulling changes, the user settings page I was meant to be modifying wouldn’t show up. I had initially placed the checkbox on the login page, which had been easier and made more sense to me, so I asked AMPATH to deviate from our mockup by switching the location of the checkbox to there and they agreed this seemed like the more intuitive choice. Getting a checkbox in the right place was easy once the app would load. The slightly more complicated part was getting the checkbox to appear only if there was an internet connection, since the option to store credentials shouldn’t be available in the offline state. I used an ngIf directive connected to a boolean value, and had the boolean update based on whether the app was online according to the online tracker service. However, the boolean appeared to be updated after the page’s HTML had already loaded, meaning the boolean was always read as its default false value. The checkbox therefore never appeared and the page didn’t update when the boolean changed. I wasn’t sure how to proceed at first, but I ended up deciding that the code controlling the online tracker dot was close enough to what I needed that I could use similar code to control the checkbox. This worked well enough, though the checkbox will simply disappear from the page if internet connection is lost in its current implementation.

Our team also restructured how we wanted to manage the branches on our repository from now on this sprint. The master branch is now a direct copy of AMPATH’s code. The branch which incorporates all our team’s edits is the offline-login branch. When we want to edit the code in the future, we’ll make our own branch for the change, push, then make a pull request to merge the branch into the offline-login branch. I’d made some edits on the offline-login branch by the time I wanted to push my changes, so I made my own branch and used git reset –hard to change the offline-login branch back to the way it had been in compliance with these new guidelines.

The teamwork keeps getting better in every regard, as with this new policy which will improve our organization and with communication. Team members answer requests for help or feedback quickly, getting back to each other within the day and sometimes within minutes.

Going forward, I want to complete the backend of the checkbox, ensuring that a user’s credentials are stored when it’s checked and that they aren’t when it’s unchecked. Both Luigi and I are assigned to this task. We also want to create documentation of our current offline-login implementation to help the AMPATH team and whoever works on our code next to understand what we’ve done so far. I have hope that we can get a decently functional implementation of the offline login done by the time the course ends.

Sprint Retrospective 4

At the beginning of this sprint, we assigned ourselves tasks to request server-side code from the AMPATH team, to design a user interface for storing credentials offline, and several tasks related to PouchDB. We decided on a UI where, when logging in while online, a user could check a box in order to store their credentials so they could later log in offline. We created a Balsamiq mockup of this design and began investigating how to store credentials so that they would be accessible offline.

We researched PouchDB to see if it would be easy enough to implement that we could create a simple mock to use in our design. In the end, we didn’t use PouchDB to store our login information. From what we could understand, while logged in, the authentication service stored encoded information about the currently authenticated user in sessionStorage. It turned out to be much simpler to create a way to log in offline by storing the same information in localStorage instead, so that the information persisted even after the session ended. In this way, a user logging in offline could have their entered credentials checked against the information stored in localStorage at the time of logging in online. George posted resources to the team channel so we could understand this approach and was successful in getting this implementation working.

sessionStorage: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage

localStorage: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

In addition this sprint, we contacted the AMPATH team to ask whether we were taking an approach they were happy with. They have not gotten back to us yet, so one of our tasks for the next sprint will be to follow up with them regarding this.

A current problem we’re facing with our implementation is that we only have one user to work with. We have no way of checking, for example, that User A can only log in if their entered credentials match User A’s stored credentials, not User B’s stored credentials. We also plan to ask the AMPATH team how to proceed in light of this, and we will possibly request another test user to work with.

Tasks to collaborate with both the team working on the offline database and the team working on encryption carried over from the last sprint. I didn’t manage to collaborate with the latter group, as they’re not far enough along for us to give each other useful information yet.

Our team worked well as usual this sprint, with members sharing our progress with each other and the class on work days, on our team channel, and on the AMPATH documentation channel. I personally spent most of this sprint improving my knowledge base so I could better serve the team in upcoming sprints. It should be easier to create concrete tasks which will get us closer to our goal now that we have a functioning implementation to work with, and I’m looking forward to contributing some work on the front end of the user interface. I think what I’ve been learning about JavaScript, the REST API, and asynchronous functions throughout this process will ultimately be useful for creating or working with any web application which involves authenticating users.

“Dig Deeper” is a pattern that I wanted to apply before I’d read about it. Ever since I started taking computer science courses past the 101 level, I’ve had the persistent nagging awareness that the knowledge I’m gaining is superficial, and there is so much more to be understood. I can feel the difference between knowing how to solve a problem and knowing why the solution is the correct one or the best option within the context of the problem. While deep understanding is a goal for its own sake for me, the writers present this as a goal because of the many problems that arise from only having a shallow understanding: being unable to fix subtle bugs, difficulty maintaining your own code, not realizing a problem you’re trying to solve has a well-known solution or is impossible to solve, and people thinking you’ve misled them about what skills you have. In addition, the lack of awareness of how little you know generates problems of its own.

To gain a deeper understanding of the technologies you use, the writers suggest reading specifications and learning from the original sources to see how the ideas came about.

I subconsciously understood this second method was important. My initial intention in studying computer science was to learn the entire history of computers as a way of discovering why things are the way they are now. I felt like I wouldn’t truly understand until I did that. Additionally, I also heard from several sources while learning C that The C Programming Language, the book co-written by the language’s designer in order to introduce it, is still the best resource there is.

The writers warn that if you apply this pattern regularly, you will naturally end up being given the most difficult assignments. This gives you the opportunity to both fail and succeed spectacularly. You will also likely be the one everyone turns to for code magic when they can’t figure out what they’re doing wrong. They advise you to continue searching for opportunities to be the worst one on a team.

This pattern is probably going to be the one that influences me the most, because it gives so many specific examples to look up of resources that lead to deeper understanding. I’m going to immediately go and apply this pattern, because I’ve been wanting to dig deeper in order to better understand the medical app we’re working on in the Software Development Capstone. Roy Fielding’s PhD thesis on REST sounds promising.

“Practice, Practice, Practice” is a pattern which encourages exactly what you’d expect: continuous practice. Like Breakable Toys, the problem this pattern is intended to address is that failure in your professional responsibilities is too costly to risk. You can’t effectively learn without the freedom to fail, though, and for that reason you need somewhere safe to practice.

This is another pattern in which the writers say the ideal application of it would be in a world with formal software apprenticeship, but in reality, software apprentices have to create an approximation for themselves. In their ideal world, a mentor would assign their apprentice practice based on the apprentice’s strength and weaknesses, reinforcing what the apprentice does well and correcting their weaknesses. The writers emphasize the need for objective metrics to evaluate your abilities as a substitute for this; if you practice without getting feedback, you will reinforce bad habits.

One way of making sure you receive regular feedback is to practice in a way that’s public to some degree. The example they give is a group that meets in person to perform code katas, exercises which are meant to help programmers to sharpen their skills through repetition. For some apprentices, an activity like this probably isn’t practical or immediately accessible. Online communities devoted to practice are another option which can likely serve as a good source of feedback. Importantly, any method of getting feedback on your practice should take place in a relaxed and playful setting, since the point is to remove the stress of mandatory success. The practice itself should be something just beyond what you know you can do easily. In having to struggle with a problem, the practice will strengthen your abilities in addition to providing the benefits of repetition.

This is a pattern that appeals to me, because I’ve discovered that I learn the most by actually writing code. To that end, the writers suggest some older books that teach important programming techniques and design principles through fun problems. This seems like a useful, concrete recommendation, and I might look into obtaining one of their suggested books or find one of my own to improve my coding skills.

Sprint Retrospective 3

Our team began work on the offline login service this sprint. We decided to first investigate AMPATH’s current login process, which turned out to be spread over many different components and services. We found where information was sent to the servers for authentication purposes and determined that what we needed to do was to point to an offline database instead of the servers. There would be no point in creating an offline login service from scratch, and in fact we needed to use their implementation if we wanted to meet the requirement of seamless transitions from online to offline and back. We created a mockup on Balsamiq of what we thought the finished login process should look like with both offline and online options. We would use the online tracker being refactored by another team to determine whether there was an internet connection, and send the user’s credentials to a server or an offline database for authentication based on the connection status. We began to think implementing this was dependent on having an offline database to work with, and we weren’t sure how to proceed before the team working on that piece completed their work.

We also learned about the bridge pattern this sprint, which we expect will be used to handle checking the online status for all the pieces of the app which will be able to function in two different modes. George posted some good resources on it to the team channel, which can be found below:


There were a couple of impediments to our progress this sprint. Multiple classes were canceled due to bad weather, and for this reason we weren’t able to collaborate as much or as effectively with the groups handling the encryption service or the offline database service as we had wanted. We did end up learning about some of the difficulties the offline database team ran into which apply to our service. They explained that patient data can’t be encrypted based on one doctor’s login information, because if it is, other doctors won’t be able to access it. They found a workaround, so going forward we’ll have a clearer idea of what’s meant to happen with the login information we send to the offline database.

The cancellations impacted our group’s ability to work together as a team as well. We do better when we can meet with each other in person and update each other on the progress we’ve been making in more detail than the stand-ups. Regardless, all team members answered the stand-ups in good detail and kept each other updated through the team channel, and I think overall our collaboration is getting better with each sprint.

One more impediment was that we discovered that we didn’t have access to server-side code to see what normally happens to the login information once it’s sent, which would inform our offline implementation if we had access to it. We plan ask the people at AMPATH whether that code can be shared with us in the near future. We also plan to make at least a mock of an offline database to use temporarily for our login service, and we might start using PouchDB ourselves if it’s not too involved. If nothing else, we will understand what the offline database team is doing better and be able to integrate our piece into the overall design more cleanly when the time comes.

I wasn’t sure if “Share What You Learn” would be applicable at my current level of experience for exactly the reason the writers give for why apprentices might have doubts about the pattern: I assumed this sort of thing should be left to people who know exactly what they’re doing. They brought up points I hadn’t considered in response to this. An apprentice’s minimal knowledge will make their explanations short and to the point, and they won’t make the mistake of assuming the people they’re sharing with have prior knowledge that they don’t. This makes their explanations, in some ways, more useful to other apprentices than an explanation from a journeyman or master.

The benefit to the apprentice sharing what they’ve learned is something I acknowledged in my blog on “Record What You Learn”: the best way you can learn something yourself is to teach it to someone else. The writers mention this benefit, but they also warn of several ways that applying this pattern can end up doing more harm than good which I hadn’t considered. Sharing your knowledge might get you into legal trouble if what you’re sharing is a trade secret, or sharing particular information may actually be harmful to others. You should be careful about what you choose to teach others, and if no one else seems to have explained it, you should consider why. Other concerns include that people might feel as though you’re bragging or explaining concepts in condescending ways if you’re not sharing with humility, or they might assume you have an ulterior motive. Conversely, the writers assert that it’s selfish to seek ways to better your own learning and not consider how others could benefit if you were to share what you know.

They suggest developing a habit of applying this pattern early on, but I still don’t feel like I’m ready to offer anything substantial. If in the near future I learn something I identify as significant enough to record it, I will remember to apply this pattern as well and write an introduction to the topic that others might find useful.

The “Reflect As You Work” pattern reminded me right away of the agile software development practice “inspect and adapt.” This practice is mentioned later in the writing as a more formal and specific version of this pattern, whereas an apprentice reflecting as they work involves self-analysis which encompasses all the projects they’ve worked on. The writers recommend periodically asking yourself whether your practices are up to date or becoming obsolete. They ask you to reflect on both the positives and the negatives about your current work, recognize how things got that way, and think about how the negatives could be improved. As one way of helping to apply this pattern, they suggest creating personal practices maps. Unfortunately the source they give for examples of this is gone, so I’m not sure what this ought to look like. I can take note of any changes in my approach as time goes on, however.

This pattern is all about maximizing the amount of useful information you get from your experiences, and utilizing it will make the difference between being an experienced developer and a skilled one; you can have lots of experiences without extracting much meaningful knowledge out of them. Therefore, the writers emphasize that your goal should be to become skilled, not experienced. I found the highlighting of this difference interesting, and it seems intuitively right that it’s possible to become experienced without gaining skill.

One of the authors is used as an example of the power of noticing and reflecting. He explained to his new teammates the pair programming technique the team used which hadn’t really been discussed, and which had simply emerged from their experiences. Once he’d noticed that this was a specific programming practice that should have a name, he blogged about it, and that quickly led him to writing columns for a prominent Software QA website. For me this connected to and reinforced broader lessons I’d already been taught about the importance of observation and noticing; the person who discovered the smallpox vaccine didn’t invent anything, just noticed that people who’d had cowpox didn’t get smallpox.

The author’s experience is also an example of another application of this pattern, which is to observe and reflect on the practices of other developers and adapt your own accordingly.

It’s already my natural inclination to reflect on what I do, so it should be no problem to incorporate this practice into my future profession.

“The White Belt” is all about setting aside your previous knowledge and approaching new situations with the mindset of a beginner. To demonstrate the general idea, the writers give the example of a family therapist who is skilled at facilitating constructive communication, but doesn’t assume he has expert knowledge on the unique circumstances of a particular family. The writers suggest learning your second language as the most likely time to run into problems from not maintaining a stance of not knowing.

I experienced this myself when learning C/C++. My first language was Java, which is object-oriented, while C is imperative. One of my biggest stumbling blocks in learning the language was failing to understand that writing classes wasn’t necessary, when I assumed it was from my knowledge of Java. I didn’t have the luxury of sacrificing productivity to spend time improving my skills, as this pattern suggests, since I was in the middle of an accelerated summer course. But I’d certainly have understood more quickly if I’d approached learning the language from the ground up. I will avoid this in the future by trying to consciously set aside my previous programming knowledge when starting a new language.

As this pattern explains, bringing your preconceptions about how things work to a new technology or context actually impedes the learning process, whereas keeping in mind that being competent in one area doesn’t mean you have expert knowledge in a different area will speed up the process. You will be open to new ideas you otherwise might not have considered.

The three side-by-side comparisons of how to generate random numbers in different languages is a good demonstration of this. Reading it for the first time was mind-blowing to me, especially the one-line solution in J. Even though such terse code comes with its own problems, it’s still effective at showing the contrast between different approaches in different languages and the benefits of setting aside the attitude that you’re already an expert. You might overlook the possibility of such a simple solution otherwise.

“The White Belt” reminds me of “Expose Your Ignorance,” because it emphasizes not allowing your fear of appearing ignorant to get in the way of your learning. In fact, the insight from this pattern I liked most was from a quote asking whether the key to a genius’s success is allowing themselves the freedom to look foolish, which we tend to interpret as eccentricity.

Sprint Retrospective 2

For most of this sprint, we tried to make progress on coming up with specific design ideas to implement the offline module. We didn’t accomplish much concretely on this front, since generating design ideas was so broad of a task that it left us without much direction. The sheer size of the application makes it difficult to parse. I believe the documentation being consolidated in the new channel about how AMPATH works will be very helpful in the coming sprints.

The concrete tasks we did manage to get done included getting ng2-amrs built on everyone’s computer and getting everyone’s local version connected to the server. We checked out Balsamiq and the wireframes there as they got added. We all read the user stories and their associated tasks.

In our most productive work class, we worked on figuring out how ng2-amrs checks whether it’s connected to the internet. We wanted to see if there was an easy way to know whether an internet connection is available and decide which version of the app a user should see and interact with based on that, for the requirement that transitions between offline and online states should be seamless. We discussed this with the group behind us, and we worked together for a bit searching for the files containing the relevant code and attempting to understand how it functioned. We also tried to decide if we should be constantly checking the status of the internet connection when we write that piece of the offline module, or if there was a more efficient way.

Although writing and submitting abstracts for posters at several events were tasks for this sprint, we ultimately decided not to do them in favor of working on tasks that applied to the application itself.

Our team worked well together this sprint. We all showed up for both work days during the week. We shared information and communicated our ideas and concerns more easily. Toward the end of the sprint, we started feeling that we wanted to focus on the offline login and offline data storage task for the offline module. We discovered on the day of the retrospective that another team had also been focusing on this task. Since they had gotten further than we had on the offline storage aspect, we decided to take the offline login piece of the task. Going forward, we’re going to make sure we have a clear understanding of what work we’re doing in relation to other teams and narrow our focus.

Mostly what I learned during this sprint was the necessity of outside research. In future sprints, I am going to dedicate more time to acquiring the knowledge and skills necessary for the tasks we’re working on. Our path forward is clearer. The AMPATH team provided some links to give us ideas for offline authentication in the google document containing the user stories. I plan on taking a look at them and working on creating something that can successfully encrypt and store a salted password locally, even if it’s not what ends up getting used in the offline module.