{"id":538,"date":"2018-09-10T15:59:58","date_gmt":"2018-09-10T20:59:58","guid":{"rendered":"http:\/\/jebware.com\/blog\/?p=538"},"modified":"2020-06-05T11:10:55","modified_gmt":"2020-06-05T16:10:55","slug":"quick-and-dirty-flat-file-storage","status":"publish","type":"post","link":"https:\/\/jebware.com\/blog\/?p=538","title":{"rendered":"Quick-and-dirty flat-file storage"},"content":{"rendered":"<h6><span style=\"font-weight: 400;\">Not every app needs cloud storage with a SQLite cache. <\/span><\/h6>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/09\/do-this-not-that.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-546\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/09\/do-this-not-that.png\" alt=\"\" width=\"864\" height=\"360\"><\/a><\/p>\n<p><span style=\"font-weight: 400;\">I\u2019m going to let you in on a little secret that helps me prototype apps quickly. &nbsp;Sometimes, when nobody&#8217;s looking, I just write my data to disk. I don\u2019t build a cloud backend. &nbsp;I don\u2019t build a SQLite database. I just serialize my data to JSON and write it to files on the disk. &nbsp;It\u2019s really easy.<\/span><\/p>\n<p><i><span style=\"font-weight: 400;\">There are definitely some drawbacks to this approach, so if your head is about to light on fire with anger towards me, skip to the <\/span><\/i><b><i>Caveats<\/i><\/b><i><span style=\"font-weight: 400;\"> section below.<\/span><\/i><\/p>\n<h2><span style=\"font-weight: 400;\">The code<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Here\u2019s what it takes; it&#8217;s just a couple of lines of Kotlin. &nbsp;Say I\u2019ve got a FooConfiguration object that I want to persist to disk. &nbsp;It\u2019s complicated enough that I don\u2019t want to put it in SharedPreferences, so we\u2019re going to write it to a file.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Step 1: We have a couple of dependencies to bring in.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><script src=\"https:\/\/gist.github.com\/jebware\/6e87f6758f32cda1599d65e73f1da914.js\"><\/script><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Step 2: we serialize the object to JSON and write it to disk.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><script src=\"https:\/\/gist.github.com\/jebware\/bb5d63adcf2840d5f41a4070253e97a2.js\"><\/script><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Step 3: When we need to read that data, we read from disk and deserialize from JSON.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><script src=\"https:\/\/gist.github.com\/jebware\/5d142777768adbaec10c1c801f51e967.js\"><\/script><\/span><\/p>\n<p><span style=\"font-weight: 400;\">That\u2019s it. &nbsp;Persistent storage, done.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Caveats<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Like I mentioned at the beginning, this is something I do to get an app idea off the ground quickly. &nbsp;When you go to scale this up, you\u2019re going to run into drawbacks.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><b>Sync &amp; conflicts<\/b><span style=\"font-weight: 400;\"> &#8211; If you try to sync this storage over a cloud file store (e.g. Dropbox, Google Drive, etc), or build some import\/export functionality, you\u2019re quickly going to run into this question &#8212; How do I handle conflicts? This is a hard problem, and the best advice is to build your storage model such that somebody else handles that complexity.<\/span><\/li>\n<li style=\"font-weight: 400;\"><b>Data model evolution<\/b><span style=\"font-weight: 400;\"> &#8211; If you change your data model, you need to ensure that it\u2019s backwards-compatible, or else you\u2019ll lose data from previously-stored objects.<\/span><\/li>\n<li style=\"font-weight: 400;\"><b>Security<\/b><span style=\"font-weight: 400;\"> &#8211; storing your data to local disk may not make sense, depending on the sensitivity of the data. &nbsp;This is highly dependent on your specific needs, but keep it in mind.<\/span><\/li>\n<li style=\"font-weight: 400;\"><b>Local-only<\/b><span style=\"font-weight: 400;\"> &#8211; The only copy of the user\u2019s data is on their device. &nbsp;If you want to build any kind of social app where users interact with each other\u2019s data, this isn\u2019t going to get the job done.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">My point here is, this isn\u2019t a perfect solution, and it may be downright bad for your app. &nbsp;Don\u2019t take my advice blindly.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Ship It<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">I have multiple apps in the Play Store using this method right now. &nbsp;No, I\u2019m not going to tell you which ones. My point is, if you\u2019re working on an app but you\u2019re getting stuck on building a backend, this is a way to punt on the complexity of your persistent storage. &nbsp;Build it quick-and-dirty for now, so you can focus on the app; revisit a more scalable solution for storage when you\u2019re ready.<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not every app needs cloud storage with a SQLite cache. I\u2019m going to let you in on a little secret that helps me prototype apps quickly. &nbsp;Sometimes, when nobody&#8217;s looking, I just write my data to disk. I don\u2019t build a cloud backend. &nbsp;I don\u2019t build a SQLite database. I just serialize my data to &hellip; <a href=\"https:\/\/jebware.com\/blog\/?p=538\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Quick-and-dirty flat-file storage&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"twitterCardType":"summary_large_image","cardImageID":0,"cardImage":"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/09\/do-this-not-that.png","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":""},"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/538"}],"collection":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=538"}],"version-history":[{"count":11,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/538\/revisions"}],"predecessor-version":[{"id":626,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/538\/revisions\/626"}],"wp:attachment":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=538"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=538"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}