Solving a Problem with an SPA
Having recently relocated to a new town, I discovered the challenge of wading through online local business listings to find relevant, accurate, up-to-date details for the businesses and services I was searching for. After speaking with long time locals and an employee from the telephone company, I discovered that a telephone directory had not been published for the area in over seven years. This is a developing country, on an island almost solely reliant on seasonal tourist dollars, which creates an atmosphere for high turn over of small local businesses causing much of the information online to be out of date, inaccurate, and many businesses have no online presence at all. The data that is available belongs primarily to large corporate entities, American chain companies, and a handful of the most heavily trafficked establishments on the island that have secured contracts with cruise-ship companies. These listings are splintered across multiple non-local webpages including trip advisor, google maps, and yelp. Often to find what you are looking for you have to visit three different sites to read ten-year-old reviews. The the following week I would have the frustrating experience of literally stumbling across a better option for the business I was searching for only one block from my house, accidentally having discovered it by taking a wrong turn or a shortcut home. I realize a directory application is not an original idea. It's not an new earth shattering original concept that is going to disrupt the face of business and marketing, but I believe that a central location for local businesses to share this information will connect customers to the services and establishments they are seeking and dramatically improve visibility and presence for smaller businesses in the area that haven't had an opportunity for exposure beyond word of mouth and local motorist traffic. I decided that this tool would be primarily used as a web application for mobile, and my design and architecture would reflect that. It would primarily include functionality to allow users to search listings by name or category, add reviews, photos, flag listings, suggest edits, and view interactive embedded google maps. I brainstormed a plan to create an admin interface to moderate user input while still filling the required application structure of an SPA (Single Page Web App).
While technically the application was SPA, a single page web app (all elements are appended to a single instance of the DOM), I really developed into something that more resembled two separate interfaces connected to a single rails api, with additional static pages. This architectural decision because any directory is only as valuable as the quality of the information contained within the database. Giving users direct access to persisting new business listings, images, and reviews meant loss of control over the quality of data being added to the directory. The application needed an interface to monitor and moderate user input while automating these administrative tasks, and a feature to grant the administrator the power to search user input, approve or decline user entries, and modify database records through the interface if needed. The current design was my imagined solution to address these concerns while still filling the technical requirements of a single page web app.
Bugs, Bumps, and Hurdles
Infinite Separation of Concerns
There was a point in the development I felt a bit like I was trapped in an infinite loop of unending separation of concerns. Most people don't that on the flip-side the of infinite expansion, is the concept of infinite contraction. Once I began to create reusable functions and methods, each seemed to divide into three more breaking down each task into smaller and more specialized components. Where does a separation of concerns end? The deeper into the infinite black hole I slipped the more complex and verbose my program became as it started to bloat with trivial code blocks handling micro tasks. That's when I knew it was time for a coffee break, a brain break, and a reset.
Using asynchronous fetch requests often created undesired effects in my program. Using asynchronous calls to the database meant the request had not returned from the server before the following functions that required this data to append to the DOM had executed creating buggy code. Testing was misleading because the the use of the debugger or pry would solve the race condition. I felt like I had too many function calls following my fetch call to use a lengthy string chained .then statements and because I know this application will be used on mobile, and that async/await does not have support for some of the older mobile browsers, I ended up using timeOut() as the solution to create a lag in execution before the data from the AJAX response was required to solve this issue.
CORS CORS CORS
If I had a penny for every time I ran smack into a CORS errors I wouldn't be writing this blog post. That's all I have to left to say about that.
Constructing Beautiful Code
There was never a point in development that I felt like I hit a brick wall and couldn't move forward. There were plenty of frustrating moments that included stumbling over new syntax, struggling to choose the right function, or library, to execute a specific task, battling with CORS errors or experiencing undesired side effects from callback functions on event listeners of particular DOM element. However, as an evolving programmer I have long since learned when to walk away, or move onto another problem, and return to a challenge with fresh eyes. Gone are the days when tired and frazzled fingers hacked away at the keyboard destroying progress by blowing up simple, elegant functions into large complicated, verbose, indecipherable pages of spaghetti code (not claiming mastery, just awareness). I am paying much closer attention to the content of each of my commits and religiously watching out for missed saves bundling with unrelated changes in the following commit. I stay focused on completing the task I am working on, and **ONLY** the task I am working on before moving on to the next. I now keep a scratchpad to jot down bugs and errors to be addressed as I discover them in the development process rather than trying to sneak unrelated changes into the current commit. Patience equals progress.
Looking back if I were to recreate this application I would have chosen token authentication over session authentication. I used what I was familiar with, but after further research, I believe token authentication is a better fit for this use case and once I complete the testing and debugging of essential features I will switch to a JSON web token authentication system. JWS is less prone to cross site request attacks, it is faster, stateless and is more efficient than trying to store cookies on mobile devices and is less prone to CORS(CROSS ORIGIN REQUEST) issues, all reasons it would be more appropriate choice.
Following completion of this project I am excited to begin actively looking for opportunities to reconnecting to, and collaborating with other programmers while beginning an active job search. My focused self imposed bubble has been productive yet isolating. As I continue refining my skills I really believe I could benefit from receiving constructive feedback, reading more repositories, exploring design patterns, studying algorithms, finding mentorship, and menteeing early programmers. I would like to dedicate more time studying code libraries, existing gem, node packages to improve my efficiency and understanding of the tools available to me. I think I still have a tendency to build the wheel from scratch when it is already designed, constructed and readily available. I look forward to continuing to refactor, maintain, and further develop my current applications, and client projects while I continue my growth as a developer refining skills in React/Redux then on to React Native. Thanks for following this journey with me.
A demo of this application can be found here!atxrenegade/Harleigh Abel