{"id":355,"date":"2024-06-23T04:44:06","date_gmt":"2024-06-23T11:44:06","guid":{"rendered":"https:\/\/kdcinfo.com\/blog\/?p=355"},"modified":"2024-06-23T13:44:28","modified_gmt":"2024-06-23T20:44:28","slug":"fun-with-practical-prototyping-project-one","status":"publish","type":"post","link":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/","title":{"rendered":"Fun with Practical Prototyping: Project One"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">&#8230; &#8230; &#8230; I relished the thought of <br>&#8230; &#8230; &#8230; &#8230; creating a &#8220;simple&#8221; open-sourced Flutter app in around three days.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">tl;dr: The functional design took a week;<br>    \u2014 read, &#8216;how three days turned into near three months&#8217;.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">On the bright side, ChatGPT and GitHub Copilot reduced the coding time by about 20-30%. What would likely have taken ~3-4 months was completed in ten weeks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Granted, a prototype isn&#8217;t meant to be a &#8220;final&#8221; product, and although there are still some features in the queue, I believe the &#8216;prototype&#8217; portion of the effort could&#8217;ve been called &#8216;done&#8217; weeks ago. But then, I love a quality working product, and, this project was as much about Flutter development practice with OOP and SOLID as it was about practical prototyping. So while I aim to continue advancing my prototyping prowess, don&#8217;t we all want what we&#8217;re working on to be the best we can make it?<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">&#8220;whatever is worth doing at all, is worth doing well&#8221;<\/p>\n<cite>Philip Stanhope, 4th Earl of Chesterfield, 1746<\/cite><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">In the end, I do aim to continue practicing prototyping (and better learning where that cutoff line is). The good news is that aside from the more critical time element of the project, and knowing I&#8217;m only a year into learning OOP and design patterns, the resulting code did indeed end up with a few intentional OOP-based structures. Plus, I can soundly say my future self will have much less anxiety going back into this project than my recent refactored apps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span style=\"text-decoration: underline;\">Project One<\/span>: <strong>Tic Tac Tuple<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The first app I opted to begin practicing practical prototyping with was Tic Tac Toe. The project was later renamed to <strong><a href=\"https:\/\/github.com\/KDCinfo\/dev-play\/tree\/main\/tic-tac-tuple\" data-type=\"link\" data-id=\"https:\/\/github.com\/KDCinfo\/dev-play\/tree\/main\/tic-tac-tuple\" target=\"_blank\" rel=\"noreferrer noopener\">Tic Tac Tuple<\/a><\/strong> in considering the game board supports three sized grids; 3&#215;3, 4&#215;4, and 5&#215;5, as well as 1-4 players. And being the art of calculating winning tiles within those grids involved chunking the tiles into tuples, thus, the name change made sense.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As referenced earlier, the architectural design of the app&#8217;s functionality took a week. Knowing <em>when<\/em> the design was &#8220;done&#8221; was a challenge in and of itself. But as with all projects, time and effort helped morph that design into class structures, and further down into properties and methods.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As the design neared completion, I was eager to start into coding via TDD. Admittedly, however, it didn&#8217;t last long. As the project wore on, testing got done mostly after coding patterns were resolved, which is how it was done for over a year at my last Flutter position. For some, TDD could well be an ever-elusive pipe dream \u2014 at least without a paradigm shift in thinking such as that between procedural and OOP.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The App<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Introducing: Tic Tac Bot<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Also referenced earlier, the Tic Tac Tuple board can be a grid of either 3&#215;3, 4&#215;4, or 5&#215;5. And with an attempt at OOP for this feature, in theory, a 6&#215;6 and 7&#215;7 could be added . . . quite . . . easily? No matter the case, the contrast in simplicity is stark in comparison if it had been done with JavaScript and PHP, as I would have back in the day (i.e. 3+ years ago). The number of players and the player symbol markers could be added to as well.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When playing with only one player, a friendly opponent, Tic Tac Bot, will join you. For some really great news, <\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">if you&#8217;ve ever wanted to win at Tic Tac Toe, <strong><em>now is your chance!<\/em><\/strong> <\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">As referenced in the &#8216;Current Shortcomings&#8217; section below, currently TicTac is only prepared to defend against wins. What that means, and what the future feature list below provides insights into, is that TicTac does not play to win, and what&#8217;s more, does not even yet check for blocks between split tiles. Those are actually future features that are slated to be bot-level difficulty preferences.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Despite Tic Tac Toe being one of the simplest games to consider creating, in hindsight, there&#8217;s a LOT that goes into creating a game (or any app) that goes beyond the creation of the game itself. Perhaps a simple 3&#215;3 grid with 2 players may have been an easier challenge, but then there&#8217;s still the game flow design, UI design and theming, images and icons, app- and local-level state management, storage, navigation, etc., etc.. Most of the initial design aspects even had to be changed along the way \u2014 so much so I had to remove the &#8216;initial design&#8217; notes from the top of the main class files (although meant as insights into the designing of the app, those notes were better suited for the readme anyways).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Current Shortcomings<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Untested on iOS.<\/li>\n\n\n\n<li>Landscape orientation may only play in portrait mode. Need to test out <code>MediaQuery.of(context).orientation<\/code> to see if it relies on layout builder constraints, which gets confused on smaller screens when the keyboard comes up thinking it switched to landscape.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Future Features<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add a light background.\n<ul class=\"wp-block-list\">\n<li>Start with showing a random image (of a few available in the <code>assets\\images\\backgrounds<\/code> folder).<\/li>\n\n\n\n<li>Later, add a background option for solid colors (maybe use a palette plugin).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Create a local logger to replace all prints, logs, and debugPrints.<\/li>\n\n\n\n<li>Create a preferences panel \u2014 possibly a bottom sheet.\n<ul class=\"wp-block-list\">\n<li>Enhance bot play: Add bot-level difficultly playing options:\n<ul class=\"wp-block-list\">\n<li>Allow Bot play to also look for its own longest range (offensive plays).<\/li>\n\n\n\n<li>Without this check (current) it only plays defensively.\n<ul class=\"wp-block-list\">\n<li><code>\/\/ Potential source: lib.src.data.models.bot_play.BotPlay.findBestTileIndex<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Add &#8216;split tile&#8217; checks for blocking (or winning) moves.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Add option to &#8216;Clear All Games&#8217; (there&#8217;s an example usage in <code>app_load_bootstrap<\/code>).<\/li>\n\n\n\n<li>The data is already available for the following features:\n<ul class=\"wp-block-list\">\n<li>Add: View all player wins (leaderboard)\n<ul class=\"wp-block-list\">\n<li>Every <code>playerId<\/code> in <code>ScorebookData.endGameScores<\/code> has a <code>PlayerData<\/code> in <code>ScorebookData.allPlayers<\/code>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Add: View previously played games\n<ul class=\"wp-block-list\">\n<li>Stored in <code>ScorebookData.allGames<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Appreciations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I truly appreciate <a href=\"https:\/\/github.com\/felangel\/bloc\" data-type=\"link\" data-id=\"https:\/\/github.com\/felangel\/bloc\" target=\"_blank\" rel=\"noreferrer noopener\">Flutter Bloc<\/a>&#8216;s separation of concerns by way of having its own <code>event<\/code> and <code>state<\/code> environments and flows. When I first developed a few apps with Provider using <code>ChangeNotifiers<\/code>, data and services became entangled. Flutter Bloc enforces data separation, and the repository pattern fully complements this separation. Learning the repository pattern with Flutter Bloc has been the most illuminating, or even freeing, for understanding the overall data flow. Granted I still call some methods directly as opposed to using a bloc or cubit, but the overall architectural scheme for the entire app is so much easier to understand than the aforementioned JavaScript and PHP approach.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I also really appreciate <a href=\"https:\/\/pub.dev\/packages\/mocktail\" target=\"_blank\" rel=\"noreferrer noopener\">Mocktail<\/a> if for nothing more than its non-use of code generation using a build runner (as Mockito does). As these projects grow, the time in having to run the build runner when classes are added or updated adds up. Additionally, Mocktail reduces the frustration of having to even be reminded to run the build runner.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">In summary&#8230;<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When trying to learn dynamic systems when working solo, I do miss the expert insights you get from working alongside inherently talented software engineers who &#8220;just get it&#8221;. They can see when you should have used composition over inheritance, when you break SOLID, and they can help isolate and break down lengthy logic conditions. In that light, I do try to tailor my GPT requests to help guide me in the right directions, but alas, because Dart is a multi-paradigm language, deriving pure OOP solutions can be challenging. This is why I&#8217;m always open to input and feedback \u2014 learning is as necessary as breathing (for me anyways).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I kept a fairly detailed log of the first month or so of development, which can be found in the source code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Source code: <a href=\"https:\/\/github.com\/KDCinfo\/dev-play\/tree\/main\/tic-tac-tuple\">https:\/\/github.com\/KDCinfo\/dev-play\/tree\/main\/tic-tac-tuple<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cheers!<br>&#8211; Keith | <a href=\"https:\/\/keithdc.com\">https:\/\/keithdc.com<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Screenshots and Dev Designs<\/h3>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-3 wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1080\" height=\"2400\" data-id=\"373\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719.png\" alt=\"Splash screen; a simple logo with a 3x3 grid and three letter Ts in tiles 0, 4, and 8 (representing a win).\" class=\"wp-image-373\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719.png 1080w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719-135x300.png 135w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719-461x1024.png 461w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719-768x1707.png 768w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719-691x1536.png 691w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013719-922x2048.png 922w\" sizes=\"auto, (max-width: 1080px) 100vw, 1080px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1080\" height=\"2400\" data-id=\"365\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498.png\" alt=\"The initial GameEntry screen where player names and the grid size of the game board can be changed.\" class=\"wp-image-365\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498.png 1080w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498-135x300.png 135w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498-461x1024.png 461w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498-768x1707.png 768w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498-691x1536.png 691w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022498-922x2048.png 922w\" sizes=\"auto, (max-width: 1080px) 100vw, 1080px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1080\" height=\"2400\" data-id=\"366\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739.png\" alt=\"An empty 4x4 playing board with two players.\" class=\"wp-image-366\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739.png 1080w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739-135x300.png 135w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739-461x1024.png 461w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739-768x1707.png 768w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739-691x1536.png 691w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719013739-922x2048.png 922w\" sizes=\"auto, (max-width: 1080px) 100vw, 1080px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1080\" height=\"2400\" data-id=\"367\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445.png\" alt=\"Tic Tac Bot is thinking...\" class=\"wp-image-367\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445.png 1080w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445-135x300.png 135w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445-461x1024.png 461w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445-768x1707.png 768w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445-691x1536.png 691w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1719022445-922x2048.png 922w\" sizes=\"auto, (max-width: 1080px) 100vw, 1080px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718786685.png\"><img loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"1280\" data-id=\"368\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718786685.png\" alt=\"Taken during development prior to the title color change, and before the winning player name selection (bolding) was fixed.\" class=\"wp-image-368\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718786685.png 720w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718786685-169x300.png 169w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718786685-576x1024.png 576w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718753109.png\"><img loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"1280\" data-id=\"370\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718753109.png\" alt=\"Translating individual tile locations to global coordinates and aligning to the grid.\" class=\"wp-image-370\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718753109.png 720w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718753109-169x300.png 169w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot_1718753109-576x1024.png 576w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"562\" height=\"428\" data-id=\"371\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_screens.png\" alt=\"This wireframe came in quite handy during initial UI development.\" class=\"wp-image-371\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_screens.png 562w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_screens-300x228.png 300w\" sizes=\"auto, (max-width: 562px) 100vw, 562px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1084\" height=\"746\" data-id=\"372\" src=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_flow.png\" alt=\"This very useful diagram is an updated flow outline depicting the connection between the bloc and the repository.\" class=\"wp-image-372\" srcset=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_flow.png 1084w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_flow-300x206.png 300w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_flow-1024x705.png 1024w, https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/devplay_tictactoe_flow-768x529.png 768w\" sizes=\"auto, (max-width: 1084px) 100vw, 1084px\" \/><\/figure>\n<\/figure>\n","protected":false},"excerpt":{"rendered":"<p>&#8230; &#8230; &#8230; I relished the thought of &#8230; &#8230; &#8230; &#8230; creating a &#8220;simple&#8221; open-sourced Flutter app in around three days. tl;dr: The functional<\/p>\n","protected":false},"author":1,"featured_media":380,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,3],"tags":[122,130,110,129,134],"class_list":["post-355","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dart","category-flutter","tag-dart","tag-design-patterns","tag-flutter","tag-oop","tag-prototyping"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Fun with Practical Prototyping: Project One - App Development: Odds and Ends<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Fun with Practical Prototyping: Project One - App Development: Odds and Ends\" \/>\n<meta property=\"og:description\" content=\"&#8230; &#8230; &#8230; I relished the thought of &#8230; &#8230; &#8230; &#8230; creating a &#8220;simple&#8221; open-sourced Flutter app in around three days. tl;dr: The functional\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/\" \/>\n<meta property=\"og:site_name\" content=\"App Development: Odds and Ends\" \/>\n<meta property=\"article:published_time\" content=\"2024-06-23T11:44:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-23T20:44:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/tic_tac_tuple_crop_1110.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1110\" \/>\n\t<meta property=\"og:image:height\" content=\"745\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Keith D Commiskey\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Keith D Commiskey\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/\"},\"author\":{\"name\":\"Keith D Commiskey\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/#\\\/schema\\\/person\\\/87980b154db7bd0cd7c569ca09328bac\"},\"headline\":\"Fun with Practical Prototyping: Project One\",\"datePublished\":\"2024-06-23T11:44:06+00:00\",\"dateModified\":\"2024-06-23T20:44:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/\"},\"wordCount\":1255,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/#\\\/schema\\\/person\\\/87980b154db7bd0cd7c569ca09328bac\"},\"image\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/tic_tac_tuple_crop_1110.png\",\"keywords\":[\"dart\",\"design patterns\",\"flutter\",\"oop\",\"prototyping\"],\"articleSection\":[\"dart\",\"flutter\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/\",\"url\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/\",\"name\":\"Fun with Practical Prototyping: Project One - App Development: Odds and Ends\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/tic_tac_tuple_crop_1110.png\",\"datePublished\":\"2024-06-23T11:44:06+00:00\",\"dateModified\":\"2024-06-23T20:44:28+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#primaryimage\",\"url\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/tic_tac_tuple_crop_1110.png\",\"contentUrl\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/tic_tac_tuple_crop_1110.png\",\"width\":1110,\"height\":745},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/2024\\\/06\\\/23\\\/fun-with-practical-prototyping-project-one\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fun with Practical Prototyping: Project One\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/\",\"name\":\"App Development: Odds and Ends\",\"description\":\"Providing insights into a career of apps and utilities that I&#039;ve conceptualized, designed, and developed; complemented with developmental journeys, findings, observations, and challenges encountered along the way.\",\"publisher\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/#\\\/schema\\\/person\\\/87980b154db7bd0cd7c569ca09328bac\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/#\\\/schema\\\/person\\\/87980b154db7bd0cd7c569ca09328bac\",\"name\":\"Keith D Commiskey\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/keith-sac-01.jpg\",\"url\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/keith-sac-01.jpg\",\"contentUrl\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/keith-sac-01.jpg\",\"width\":113,\"height\":117,\"caption\":\"Keith D Commiskey\"},\"logo\":{\"@id\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/keith-sac-01.jpg\"},\"description\":\"Web App Creator; Former Flutter Developer; Former Front End Developer; Former Technical Graphics.\",\"sameAs\":[\"https:\\\/\\\/kdcinfo.com\\\/blog\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/commiskey\"],\"url\":\"https:\\\/\\\/kdcinfo.com\\\/blog\\\/author\\\/kdc4wp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Fun with Practical Prototyping: Project One - App Development: Odds and Ends","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/","og_locale":"en_US","og_type":"article","og_title":"Fun with Practical Prototyping: Project One - App Development: Odds and Ends","og_description":"&#8230; &#8230; &#8230; I relished the thought of &#8230; &#8230; &#8230; &#8230; creating a &#8220;simple&#8221; open-sourced Flutter app in around three days. tl;dr: The functional","og_url":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/","og_site_name":"App Development: Odds and Ends","article_published_time":"2024-06-23T11:44:06+00:00","article_modified_time":"2024-06-23T20:44:28+00:00","og_image":[{"width":1110,"height":745,"url":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/tic_tac_tuple_crop_1110.png","type":"image\/png"}],"author":"Keith D Commiskey","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Keith D Commiskey","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#article","isPartOf":{"@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/"},"author":{"name":"Keith D Commiskey","@id":"https:\/\/kdcinfo.com\/blog\/#\/schema\/person\/87980b154db7bd0cd7c569ca09328bac"},"headline":"Fun with Practical Prototyping: Project One","datePublished":"2024-06-23T11:44:06+00:00","dateModified":"2024-06-23T20:44:28+00:00","mainEntityOfPage":{"@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/"},"wordCount":1255,"commentCount":1,"publisher":{"@id":"https:\/\/kdcinfo.com\/blog\/#\/schema\/person\/87980b154db7bd0cd7c569ca09328bac"},"image":{"@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#primaryimage"},"thumbnailUrl":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/tic_tac_tuple_crop_1110.png","keywords":["dart","design patterns","flutter","oop","prototyping"],"articleSection":["dart","flutter"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/","url":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/","name":"Fun with Practical Prototyping: Project One - App Development: Odds and Ends","isPartOf":{"@id":"https:\/\/kdcinfo.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#primaryimage"},"image":{"@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#primaryimage"},"thumbnailUrl":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/tic_tac_tuple_crop_1110.png","datePublished":"2024-06-23T11:44:06+00:00","dateModified":"2024-06-23T20:44:28+00:00","breadcrumb":{"@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#primaryimage","url":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/tic_tac_tuple_crop_1110.png","contentUrl":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2024\/06\/tic_tac_tuple_crop_1110.png","width":1110,"height":745},{"@type":"BreadcrumbList","@id":"https:\/\/kdcinfo.com\/blog\/2024\/06\/23\/fun-with-practical-prototyping-project-one\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kdcinfo.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Fun with Practical Prototyping: Project One"}]},{"@type":"WebSite","@id":"https:\/\/kdcinfo.com\/blog\/#website","url":"https:\/\/kdcinfo.com\/blog\/","name":"App Development: Odds and Ends","description":"Providing insights into a career of apps and utilities that I&#039;ve conceptualized, designed, and developed; complemented with developmental journeys, findings, observations, and challenges encountered along the way.","publisher":{"@id":"https:\/\/kdcinfo.com\/blog\/#\/schema\/person\/87980b154db7bd0cd7c569ca09328bac"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kdcinfo.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/kdcinfo.com\/blog\/#\/schema\/person\/87980b154db7bd0cd7c569ca09328bac","name":"Keith D Commiskey","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2023\/08\/keith-sac-01.jpg","url":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2023\/08\/keith-sac-01.jpg","contentUrl":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2023\/08\/keith-sac-01.jpg","width":113,"height":117,"caption":"Keith D Commiskey"},"logo":{"@id":"https:\/\/kdcinfo.com\/blog\/wp-content\/uploads\/2023\/08\/keith-sac-01.jpg"},"description":"Web App Creator; Former Flutter Developer; Former Front End Developer; Former Technical Graphics.","sameAs":["https:\/\/kdcinfo.com\/blog","https:\/\/www.linkedin.com\/in\/commiskey"],"url":"https:\/\/kdcinfo.com\/blog\/author\/kdc4wp\/"}]}},"_links":{"self":[{"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/posts\/355","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/comments?post=355"}],"version-history":[{"count":17,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/posts\/355\/revisions"}],"predecessor-version":[{"id":385,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/posts\/355\/revisions\/385"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/media\/380"}],"wp:attachment":[{"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/media?parent=355"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/categories?post=355"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kdcinfo.com\/blog\/wp-json\/wp\/v2\/tags?post=355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}