Harleigh Abel

Harleigh Abel

Harleigh Abel

Harleigh-Abel-profile-pic
Directory Cozumel Screen Shot
Software Development

DEVELOPING DIRECTORY COZUMEL

Feburary 12 2020
10 min read
#javascript #railsapi #fullstack #cozumel #flatironschool #webdev

Solving a Problem with an SPA


When I initially began this project it was to be part two an existing rails Trail Tracker app I had already constructed. Midway through requirements changed from developing JavaScript elements for the existing application to the development of a new single page web app. I pivoted from my current project to accommodate these changes. The new requirements outlined development for an SPA constructed with an HTML, CSS, and "vanilla" JavaScript front-end, and rails API back-end, using Restful conventions, CRUD functionality, JavaScript object classes in traditional OOP style encapsulating related data and behavior, and AJAX/Async client-server interactions using JSON data format for these requests.

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).


Wikipedia definition of a Single Page Web Application

While technically my application qualifies as 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. This architectural decision was made when I realized that 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. I wanted a way monitor and moderate user input while automating these administrative tasks, and to add 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. While the application does make use of JavaScript classes and objects for users to interact with, I think that it is more reflective of procedural programming style. With a heavy separation of concerns, it is broken down more into interfaces than object classes which seemed more natural architectural style from my desired user/admin perspective.


Hello JavaScript!


While I have worked with JS in labs and lessons this is was my first actual JS application. Transitioning from object oriented ruby, and working with frameworks like Rails and Sinatra, "vanilla" JavaScript felt clunky and slow. Not slow to execute, but slow to build with. Having to create each new element, locate a an existing element to append to, append each element to the DOM, add individual event listeners and callback function for every single action on the page seemed a bit like trying to build a cross country railway out of toothpicks. However once I got more familiar with the syntax and got into the zone, my productivity increased, and my working knowledge of C allowed me to appreciate how much more developer friendly a scripting language like JS actually is.


An "Ah-haaaaaa!" Moment


As my first JS/Rails API application, I felt a bit like I was building a house without having ever seen one before. I knew what doors and walls looked like but wasn't 100% clear about how all the pieces fit together. In the beginning of my development process I was essentially building things twice. I did not have the foresight or experience to see repeating patterns and reusable pieces of code until after I have constructed them. Using the house construction analogy that I commonly refer to when explaining programming concepts to my mechanically inclined but technology illiterate partner: I would design and build a door from scratch, a window from scratch, a wall from scratch, then when once I realized these were going to be common reusable pieces, these would become my templates for my door, window, and wall factories to replicate as many of these pieces as needed. The 'Ahhaaa!' moments came about midway through when I was able to foresee which functions and variables I would need to repeat and construct them dynamically to accept the parameters I would require in the future to and predict what desired behaviors these functions should have for future features and development.


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.



Separation of Concerns

ASYNC JS


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


I am always striving to improve my code, syntactically, architecturally, UX design, speed and efficiency. Two areas specific areas I would like to work on are: creating non-invasive JavaScript, and writing pure functions. I try to keep these in the back of my mind as I have a long way to go to master these area. Remembering that a pure function 'given the same input, will always produce the same output, and has no side effects', reminds me that some of the benefits of pure functions include their independent nature, which makes then easy to move, organize and refactor. Pure functions are more flexible, adaptable and immune to exposure to bugs caused by shared mutable state.


Pure Function

Even though this was my first JS application, 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.


In Retrospect


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.

Since this project’s scope had already exceeded the requirements, I had to impose a cut off point that meant some of the features I envisioned for my final product didn't make the cut. I will continue to work on styling/aligning forms, reviews, and photo content in adjustable grid with media queries to fit both desktop and mobile views. I will add google maps geo encoding to the admin panel to automate google map object creation using street addresses instead of longitude and latitude coordinates. I may create a feature that displays a map of the nearest businesses matching a users search results in relation to their current location. I would also like to move data stored in global variables to the JavaScript localStorage object on the DOM, and user uploaded images to the database rather than referring to external links.


Looking Ahead


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, while I continue my growth as a developer in anticipation of the addition of React/Redux to my toolset and eventually the exploration of React Native. Thanks for following this journey with me.





A demo of this application can be found here!

atxrenegade/Harleigh Abel


Post Comments

Leave A Reply