<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chloe</title>
    <description>The latest articles on DEV Community by Chloe (@chloeglowy).</description>
    <link>https://dev.to/chloeglowy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F991119%2F47b44a20-8275-42dd-97e4-d6be0f60e54b.jpeg</url>
      <title>DEV Community: Chloe</title>
      <link>https://dev.to/chloeglowy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chloeglowy"/>
    <language>en</language>
    <item>
      <title>Free Time Helper - a new project</title>
      <dc:creator>Chloe</dc:creator>
      <pubDate>Wed, 28 Dec 2022 00:02:03 +0000</pubDate>
      <link>https://dev.to/chloeglowy/free-time-helper-a-new-project-4k72</link>
      <guid>https://dev.to/chloeglowy/free-time-helper-a-new-project-4k72</guid>
      <description>&lt;p&gt;I'm thinking of starting a new project called Free Time Helper. This article has two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is the project? What are the core use cases?&lt;/li&gt;
&lt;li&gt;What are the APIs? What is the core of the architecture?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  User-initiated Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;I don't know what I want to do right now&lt;/li&gt;
&lt;li&gt;I ask the system what to do. I tell it how much &lt;strong&gt;free time*&lt;/strong&gt; I have right now.&lt;/li&gt;
&lt;li&gt;The system gives a Suggestion, which may either be a Question or an Activity.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;* &lt;strong&gt;free time&lt;/strong&gt;: how much time is there between now and the next time I intend to do something else, such as get ready for bed, go to work, leave for an appointment, etc.?&lt;/p&gt;

&lt;h3&gt;
  
  
  System-initiated Flow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The system gives a Suggestion&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Question
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The system asks me a question. For example:

&lt;ol&gt;
&lt;li&gt;What's something that energizes you?&lt;/li&gt;
&lt;li&gt;What's your best friend's name?&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;I can either:

&lt;ol&gt;
&lt;li&gt;Send an answer to the system

&lt;ol&gt;
&lt;li&gt;The system gives a new Suggestion&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Tell the system "I don't want to answer this question right now"

&lt;ol&gt;
&lt;li&gt;The system gives a new Suggestion&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Do nothing

&lt;ol&gt;
&lt;li&gt;The system does not communicate with me until I initiate contact with it again&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Activity
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The system suggests an activity. For example:

&lt;ol&gt;
&lt;li&gt;text {best friend}&lt;/li&gt;
&lt;li&gt;do {thing that energizes you}&lt;/li&gt;
&lt;li&gt;spend 5 minutes outside&lt;/li&gt;
&lt;li&gt;listen to your favorite song&lt;/li&gt;
&lt;li&gt;Read a specific article&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;I can either:

&lt;ol&gt;
&lt;li&gt;Tell the system I accept the suggestion

&lt;ol&gt;
&lt;li&gt;I take some time to do the suggested activity&lt;/li&gt;
&lt;li&gt;I tell the system I am done with the suggested activity.&lt;/li&gt;
&lt;li&gt;The system gives a new Suggestion&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Tell the system I do not accept the suggestion

&lt;ol&gt;
&lt;li&gt;The system gives a new Suggestion&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Do nothing

&lt;ol&gt;
&lt;li&gt;The system does not communicate with me until I initiate contact with it again&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Software Architecture
&lt;/h2&gt;

&lt;p&gt;As usual I will be using the &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"&gt;Clean Architecture&lt;/a&gt;. As a starting exercise, I've made a diagram showing the interfaces of the innermost ring, the "Entities" or "Enterprise Business Rules" ring. Here, I'm referring to this ring as the "Core" component, since that's more intuitive to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--02lHP0NA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmoiu2heil2hzfl1x44r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--02lHP0NA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmoiu2heil2hzfl1x44r.png" alt="Architecture Diagram" width="880" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start out with, I tried to imagine the system as having a lot of advanced features, most of which I will probably never get to, and make sure that the interfaces work with all of these. Some advanced features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Machine learning to estimate how "helpful" (this is intentionally vague) each suggestion will be for each user&lt;/li&gt;
&lt;li&gt;A system-initiated communication channel (i.e., notifications) where the system can proactively make suggestions to the user&lt;/li&gt;
&lt;li&gt;Extensions, to allow the user to provide additional information about themself to the system automatically, via integrations with other software systems that already have information about them&lt;/li&gt;
&lt;li&gt;End to end encryption&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, I thought about different ways the system could be deployed, and tried to make sure the Core component does not depend on any specific one. For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The system could be deployed using any database or persistence framework&lt;/li&gt;
&lt;li&gt;The system could be deployed using a traditional, separated client-server-database architecture, or it could run entirely on a single machine (e.g., a phone) with the option to have cloud backups. This would allow support for end-to-end encryption.&lt;/li&gt;
&lt;li&gt;It could use any (or no) API framework or RPC framework&lt;/li&gt;
&lt;li&gt;The user interface could use any communication medium, including a webpage, a mobile phone app, an Alexa skill, a chatbot, a doll that follows you around and talks to you, or a chip in your brain&lt;/li&gt;
&lt;li&gt;It could be implemented in any programming language and run on any machine&lt;/li&gt;
&lt;li&gt;In fact, it could be implemented as a protocol written in English and put in a binder for a person to follow. They could accept calls over the phone. The user facts storage implementation could be a filing cabinet, the suggestions catalogue could be a binder, the prediction model could be a person who gives an estimate based on their intuition, and notifications could be implemented by another person who calls the user on the phone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I currently don't see limitations to this architecture, but I'm guessing some will arise as I flesh out the details of the interfaces. For example, what are all the fields in an "action a user took"? What is in a "catalogue entry"?&lt;/p&gt;

&lt;p&gt;As a final part of this exercise (for now), I pared down the diagram to contain only interfaces I think are needed for a minimum viable product:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wz1hoUe9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ihwu4nvlx8suxoo8tx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wz1hoUe9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ihwu4nvlx8suxoo8tx4.png" alt="Pared down architecture" width="880" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My next goal is to flesh out all the interfaces. What exactly are the fields in all the objects that are passed in and out of the methods and plugins?&lt;/p&gt;

&lt;p&gt;As a next step towards this, I think it would be helpful to write out some examples of suggestions (activities and questions), actions a user took, and what the catalogue (set of information that helps us decide what activities a user might be interested in based on their history) might look like.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devjournal</category>
      <category>design</category>
    </item>
    <item>
      <title>Pushing testing inward</title>
      <dc:creator>Chloe</dc:creator>
      <pubDate>Fri, 16 Dec 2022 20:49:10 +0000</pubDate>
      <link>https://dev.to/chloeglowy/pushing-testing-inward-25d4</link>
      <guid>https://dev.to/chloeglowy/pushing-testing-inward-25d4</guid>
      <description>&lt;p&gt;Recently I've been working on rewriting &lt;a href="https://dev.to/chloeglowy/what-is-dandelion-3ldi"&gt;Dandelion&lt;/a&gt; to use &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"&gt;Clean Architecture&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Right now, the architecture for the parts I've rewritten looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BKrusp2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brn8m628oscf2awqijhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BKrusp2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brn8m628oscf2awqijhi.png" alt="Architecture Diagram" width="880" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of arrows, and I'd like to simplify that, but the important part is that they all point inwards. Lower-level (farther out) components depend on higher-level (farther in) components. This is the &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"&gt;Dependency Rule&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So far, during my rewrite, I've been testing things as I go using the GraphiQL UI. This has been helpful for making me confident things are working end-to-end, including GraphQL, MongoDB, Express, and Passport.&lt;/p&gt;

&lt;p&gt;However, starting yesterday I'm trying to test using Jest tests instead. Right now I'm testing at the "Interface Adapters" area, meaning I'm testing everything inward of this circle. My tests are testing Enterprise Policy (Entities), Application rules (Interactors), and Interface Adapters (Controllers and Presenters.)&lt;/p&gt;

&lt;p&gt;Doing this in addition to (if not instead of) GraphiQL testing has a couple advantages:&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm forced to see where my Mongodb plugin has unneeded complexity
&lt;/h2&gt;

&lt;p&gt;For the tests, I'm writing an in-memory "database" plugin and using that instead of the Mongodb plugin. To get the tests passing, the plugin needs to be able to achieve the same things the Mongodb plugin achieves.&lt;/p&gt;

&lt;p&gt;They're both using an abstract plugin interface, which is a great start for separating database/persistence/storage code from enterprise/application code. However, as I write the new in-memory plugin, I've noticed that the Mongodb plugin does some things that aren't strictly necessary for persistence or performance, such as privacy checks.&lt;/p&gt;

&lt;p&gt;There also are a &lt;em&gt;lot&lt;/em&gt; of type-switching factories in my code. There are several different types of history events that can exist on an aid request -- it was created, someone commented, someone started working on it, the recipient name was changed, etc. Since history events can be represented in multiple different contexts, e.g., pre-commit, post-commit, application code, DB-specific code, there are multiple places where all of these different types of history events are implemented as several different classes implementing the same interface.&lt;/p&gt;

&lt;p&gt;Maybe I will find a better solution to this eventually. However, the takeaway for this post is that the Mongodb plugin has a couple of different type-switch factories to convert subclasses of one interface into subclasses of another interface, and now I'm having to re-implement that in my in-memory DB plugin. Going through the process of writing a test plugin is making me see where there's an opportunity for code simplification.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm forced to revisit the interface between GraphQL and the controllers.
&lt;/h2&gt;

&lt;p&gt;The test code I'm writing is similar to the GraphQL resolver code, in that it calls controllers and then examines the values in the presenters that are returned. &lt;/p&gt;

&lt;p&gt;When writing tests, I like to make the interfaces between the test code and the application code as simple and clear as possible. I also like to keep logic out of the test code where possible.&lt;/p&gt;

&lt;p&gt;I'm currently having to implement a lot of logic in test code and sometimes bypass the controller interfaces. This is showing me opportunities for improving these interfaces.&lt;/p&gt;

&lt;p&gt;There's a clear path to improving the interfaces of the controllers: Do whatever makes the tests simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's easier to think about what use cases I want to support
&lt;/h2&gt;

&lt;p&gt;There are a lot of new features I want to support in the app. However, it can be overwhelming to think about supporting them through all the parts of the codebase, including entities, interactors, controllers, Mongodb, GraphQL, UI design, and UI implementation.&lt;/p&gt;

&lt;p&gt;Now, thinking of the tests as another "client" of the application, I don't have to support all those parts. I just have to support entities, interactors, and controllers. And mock plugins for the framework/DB adapters.&lt;/p&gt;

&lt;p&gt;With this simplified scope, it's a lot easier to think through the interfaces and requirements for the next few things I want to do, such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allow people to create their own accounts&lt;/li&gt;
&lt;li&gt;Allow people to create their own sharing groups&lt;/li&gt;
&lt;li&gt;Allow people to add other people to their sharing groups&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And, as a final bonus (this is one of the main purposes of Clean Architecture), after implementing these new use cases with the tests as the client, I can be confident these inner rings of the architecture will still continue to work well even if I switch to a different database, API framework, or execution environment.&lt;/p&gt;

&lt;p&gt;As I progress, I'd like to think about moving my tests even further inwards -- unit testing some of the modules within the Entities directly, and then move out to testing the Use Cases directly, without going through the controllers. This might allow me to develop new use cases and/or controllers more easily and confidently, since the interfaces of these inner layers will be cleaner, more complete, and better tested. However, it's also possible the level of overhead (in terms of code maintenance) required for this much testing will be excessive. We'll find out as we go!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>webdev</category>
      <category>devjournal</category>
      <category>architecture</category>
    </item>
    <item>
      <title>What is Dandelion?</title>
      <dc:creator>Chloe</dc:creator>
      <pubDate>Fri, 16 Dec 2022 00:34:46 +0000</pubDate>
      <link>https://dev.to/chloeglowy/what-is-dandelion-3ldi</link>
      <guid>https://dev.to/chloeglowy/what-is-dandelion-3ldi</guid>
      <description>&lt;p&gt;I'm going to write a series of posts about a project I'm working on called Dandelion. &lt;/p&gt;

&lt;p&gt;The purpose of this post is to give an overview of what Dandelion is so I can reference it as context in other posts.&lt;/p&gt;

&lt;p&gt;Dandelion is: &lt;/p&gt;

&lt;h2&gt;
  
  
  A mobile web application for collaboratively helping people who need things.
&lt;/h2&gt;

&lt;p&gt;Specifically, it was originally developed for a group of people (volunteers) who visit people who are living outside (residents) and offer help. Residents ask for things like batteries, tents, boots, propane stoves, etc.&lt;/p&gt;

&lt;p&gt;When a resident tells a volunteer that they need something, the volunteer can record the request on Dandelion. Currently, in the code, we refer to this recorded request as an &lt;strong&gt;AidRequest&lt;/strong&gt;. Volunteer can mark themselves as working on an aid request, mark it as complete, comment on it, tag other volunteers, and more. In a future post, I'll describe the features in more detail.&lt;/p&gt;

&lt;p&gt;The app hasn't been used by actual volunteers since about October 2022, and I'm not actively promoting it for real-life use as of 12/15/22. In the future, when the app supports more features, this may change.&lt;/p&gt;

&lt;p&gt;For now, I'm using the app as a pet software project to which I can apply new concepts that I learn.&lt;/p&gt;

&lt;p&gt;Here's a non-exhaustive list of things I'm considering learning by applying them to Dandelion:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Different authentication methods, e.g., sign in with Google, email a magic link&lt;/li&gt;
&lt;li&gt;Multi-Factor Authentication&lt;/li&gt;
&lt;li&gt;Protection from DDOS&lt;/li&gt;
&lt;li&gt;Protection from XSS&lt;/li&gt;
&lt;li&gt;Serving static assets through a CDN&lt;/li&gt;
&lt;li&gt;Using spritesheets&lt;/li&gt;
&lt;li&gt;Adapting the app to be open to the public, rather than allowlist-only&lt;/li&gt;
&lt;li&gt;Unit testing under Clean Architecture, using a test API&lt;/li&gt;
&lt;li&gt;React testing&lt;/li&gt;
&lt;li&gt;Using different kinds of databases (it currently only supports MongoDB)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I don't know if anyone is going to read this, but if you do, feel free to comment other things I could try learning with this project :)&lt;/p&gt;

&lt;p&gt;In my next post, I'll describe the existing features of Dandelion and some features I want to add to it next. After that, I'll dive into my current project, which is refactoring the backend to use Clean Architecture. &lt;/p&gt;

&lt;p&gt;All my posts will be on &lt;a href="https://github.com/chloe-glowy/blog/tree/main/dandelion" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and my &lt;a href="https://dev.to/chloeglowy"&gt;DEV page&lt;/a&gt;. The source code for this post is on GitHub &lt;a href="https://github.com/chloe-glowy/blog/blob/main/dandelion/what-is-dandelion.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The source code for Dandelion is on GitHub &lt;a href="https://github.com/chloe-glowy/dandelion" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Demo Video:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fchloe-glowy%2Fblog%2Fblob%2Fmain%2Fdandelion%2Fassets%2Fezgif-2-d00a0ad6da.gif%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fchloe-glowy%2Fblog%2Fblob%2Fmain%2Fdandelion%2Fassets%2Fezgif-2-d00a0ad6da.gif%3Fraw%3Dtrue" alt="Demo Video" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
