Freelancing

What I learned from the hardest site I’ve ever tried to build

I know I’m not the most experienced developer in the world, but by golly I’ve built stuff. From marketplace apps to learning portals to an iOS building management app backed with a Rails backend. I’ve even built an image recognition app!

All this isn’t to brag, no sir. Just to show that I’ve actually built things, some of which were even mildly complex. All of the above though, paled in comparison to The Hardest Thing I’ve Ever Tried To Build™.

Ok enough dramatics, I was actually just trying to build my own personal site. Something simple to display my portfolio of work, maybe a contact form so people can get in touch. How hard could it be?

Very hard as it turns out.

After getting a neat coupon code from the The Guardian Football Weekly Podcast, I decided to try using Squarespace. It is the all-in-one solution for anyone looking to create a beautiful website (as per their own website). They were kind enough to give me a 14 day trial and their documentation is in video form!

Note to self : When I finally build my SAAS product, use videos for documentation, it makes things so much easier.

 You don’t really have to write any code in Squarespace. Its all drag and drop. They also give you a theme to get started, this is actually pretty good UX. Nothing makes people disappear faster then a blank canvas.

So Squarespace is pretty blameless in this, they actually provided everything I needed to build my site. The biggest barrier to building my site was in fact, myself.

I had no idea what content to put in my site, I’ve heard of copywriting, but I never though it would be this hard. Apparently just writing :

“Here’s my site, this is what I do. Hire Me!!!!”

Is nowhere near enough.

I read a few copywriting books to see if I can get better. I recommend CopyHackers, their books were really good. I applied their advice and I guess I created some half-way decent copy.That was then I realised my main enemy was’t bad copywriting.

It was fear.

I was worried, scared even. I was worried about what people will think of my site, will people spam my contact form with insults about my design, writing and my mother? Will people in the street point and laugh at me? Will children heckle me in the street and throw stones at my car?

That was when it hit me.

THIS IS THE REASON CLIENTS SEEM SO ‘PICKY’

This is the reason they ask for little changes all the time. This is the reason they seem so needy. This is the reason they never seem satisfied.

To me, this is just another app. But to the client, this is their creation, their baby. To some clients, the app I’m building is a useful add on to their business, to others it IS their business. Is it any wonder they act like helicopter parents? Hovering over you to make sure you don’t screw up?

This is one thing that separates good freelancers and bad freelancers, its important that the client trusts you before, during and even after a project. I can verify from experience that once your client has doubts about you, they go into Pointy Haired Boss in Micromanaging mode.

I probably lack this skill as of right now, its probably something I should work on for 2017.

P.S So what happened to the Squarespace site you ask? Is it live? Well….after my trial expired I was all ready to upgrade to the Basic Plan. Sadly, Squarespace rejected my card, so its back to WordPress for me!
Ruby, Ruby on Rails

Rake:notes FTW!

I just found a really cool feature in Rails, can’t believe I didn’t know about it before.

Apparently you can add comments like this in your Rails app

    def uncompleted_method
      # TODO complete this method
    end

And if you run `rake:notes` in your terminal, it will list down all the TODO comments like so

rake-notes-todo

You can also use `optimize` and `fixme` with rake:notes.

    def need_to_fix
      # FIXME fix this quickly
    end

    def optimize_this
      # OPTIMIZE this is way too slow
    end

Running rake:notes will give you:

rake-notes-todo-2

This is a really useful technique to maintain a running todo list/ reminder system in your Rails app

Ruby, Ruby on Rails

Around callbacks in ActiveRecord

Callbacks are methods that get called at certain moments of an object’s life cycle. If you’re wondering why the above sentence sounds so coherent, its because I stole it verbatim from the Rails Guides.

So most people are pretty familiar with before and after callbacks. before_save and after_update pretty much explains itself. There is another type of callback though, called around.

What in the world does it do?

What it does is it allows you to run code both before and after an operation. So an example will be like this:


class Facility < ActiveRecord::Base
  
  around_save :method_around_save
  
  private 
    def method_around_save
    # you can do stuff here
      yield <---- the save happens here
    # you can continue doing stuff here as well
    end
end

So why is this useful? Whats the difference between this and doing 2 separate before_save and after_save callbacks?

In my opinion, the around callback could be useful if you want all your database transactions in your callbacks to be atomic.

Or if you want whatever you’re doing in after_save depends on what happens before_save

Lets have a concrete example, based on a make-believe real life scenario

Say you have a Building model, which has a number of facilities under it.
Every time a building is created, you want to create a set number of hardcoded facilities.

  class Building < ActiveRecord::Base

  has_many :facilities

  after_create :create_facilities
 
  def create_facilities
    #Do facility creation here
  end
end

So each facility, will have a number of sub-facilities (Just like how badminton courts have Court A, Court B, etc). These sub-facilities are also created when the a facility is created

class Facility < ActiveRecord::Base
  after_create :create_subfacilities

  def create_subfacilities
    # sub-facilities will be created here.
  end
end

So this looks ok, I guess. But what if someone updates the facility? Maybe the user made a mistake and set the number of sub-facilities to 2 when actually there were 3 sub-facilities?

One way is to do a check before the update happens to see if the number of sub-facilities has changed (before_update) and then update the sub-facilities after the facility has been updated (after_update)

Something like this maybe?

class Facility < ActiveRecord::Base
  after_create :create_subfacilities
  before_update :check_for_subfacility_change
  after_update :sync_subfacility

  def check_for_subfacility_change
    @sync? = true if #subfacility has been changed
  end

  def sync_subfacility
    #update number of sub-facilities based on the value of @sync?
  end

  def create_subfacilities
    # sub-facilities will be created here.
  end
end

I’m just guessing here, but perhaps this could be a bit difficult to read after a few months and when the class gets bigger. So it could be easier if we did the whole thing in one around_update callback.

Perhaps something like this

class Facility < ActiveRecord::Base
  after_create :create_subfacilities
  around_update :sync_subfacility

  def sync_subfacility
   sync? = true if #subfacility has been changed
   yield
   #update sub-facilities if sync? is true
  end

  def create_subfacilities
    # sub-facilities will be created here.
  end
end

So there you go, hopefully that made sense. If you can think of a better way please reply in the comments

Ruby, Ruby on Rails

Group_by – The Definitive Guide

I’ve been working on a Rails API that sends JSON goodness to a mobile app. Its the first major app I’ve done that involves me doing the API side.

(I’ve learned that designing APIS is NOT as easy as I thought. Especially when other people have to use them.)

One of the things I had to do was to send a json load of bookings grouped by the
type of facility that was booked.

I admit I don’t religiously read the API docs for any programming language I work on, so I was embarrassingly excited when I found the group_by method

Lets read the official explaination

Collect an enumerable into sets, grouped by the result of a block. Useful, for example, for grouping records by date.

So lets break it down

1) It takes an enumerable, and like all enumerables it iterates through its contents

2) It then groups everything it iterates based on the results of the block

So imagine I had an ActiveRecordRelation with 3 booking objects

@bookings = [
  # 1,
    :facility_name => "BBQ",
    :booking_date => Wed, 30 Nov 2016>,
  # 3,
    :facility_name => "Sauna",
    :booking_date => Wed, 23 Nov 2016>,
  # 2,
    :facility_name => "BBQ",
    :booking_date => Thu, 24 Nov 2016>
]

So what if I want to group these bookings by facility name? I would do something like this.

   grouped_bookings = @bookings.group_by{ |b| b.facilty_name }

grouped_booking will return

@bookings = 
  {
    "BBQ" => [
    # 1,
      :facility_name => "BBQ",
      :booking_date => Wed, 30 Nov 2016>,
    # 2,
      :facility_name => "BBQ",
      :booking_date => Thu, 24 Nov 2016>
  ],
    "Sauna" => [
      # 3,
      :facility_name => "Sauna",
      :booking_date => Wed, 23 Nov 2016>,
    ]
  }

iOS, Swift

Time Zone fun with NSDate

The other day I had to build a booking feature where users can select a date to book a facility with a calendar.

It worked well enough, when the dates were clicked an NSDate was produced. That NSDate could then be sent to our Rails backend to store the booking.

I noticed however, that the NSDate received from the calendar gave a date from the UTC timezone.

Now, a slight segue about NSDates. According to the Apple docs

NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).

Basically it means that an NSDate is a certain amount of integers (I assume its seconds but the Apple Docs don’t say anything about that) away from 00:00:00 UTC on 1 January 2001.

So this makes the idea of a timezone for NSDate pretty meaningless.

Thankfully, we can use NSDateFormatter to create string versions of NSDates. The NSDateFormatter has a property called timeZone that can be used to convert a NSDate to a String with the set timezone. The way I used it was as below

    func convertTimeZoneDateToString(date: String) -> String {
        let dateString = String(date)
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzzz"
        let dateObj = dateFormatter.dateFromString(dateString)
        var formattedDateString = dateFormatter.stringFromDate(dateObj!)
        dateFormatter.dateFormat = "dd-MM-yy"
        dateFormatter.timeZone = NSTimeZone(name: "MYC")
        formattedDateString = dateFormatter.stringFromDate(dateObj!)
        return formattedDateString
    }

So this will return a date with the format “dd-MM-yy” and follows the Malaysian timezone.

So thats now all well and good, but then I got a feature request where we only want to limit booking dates to 3-5 days ahead.

It would be pretty easy to compare NSDates together, we could use something like this.

    func differenceBetweenDate(currentDate: NSDate, selectedDate: NSDate) -> Int {
        let userCalendar = NSCalendar.currentCalendar()
        let dayCalendarUnit: NSCalendarUnit = [.Day]
        let dayDifference = userCalendar.components(
            dayCalendarUnit,
            fromDate: currentDate,
            toDate: selectedDate,
            options: [])
        return dayDifference.day
    }

This will return an integer of the difference in days.

Sadly,since the calendar returns a NSDate in UTC timezone, it can cause some predictable bugs since the app is supposed to live in Malaysia.

Using the earlier method wont cut it as it returns a String. So how?

After giving it some thought, I decided on doing using the string from the convertTimeZoneDateToString method and use regex to parse out the day/month/year from it. From there we can use NSDateComponents to create NSDates with the correct timezone.

Below is the method used to parse the dates with regex

    func matchesForRegexInText(regex: String!, text: String!) -> [String] {
        
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = text as NSString
            let results = regex.matchesInString(text,
                                                options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substringWithRange($0.range)}
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }

An example for using this method will be:

  let date = "22-03-16"
  let dateArray = matchesForRegexInText("[0-9][0-9]", text: date)
  //dateArray = ["22","03","16"]

So then we can use NSDateComponents to create a new date. An example is:

  let date = "22-03-16"
  let calendar = NSCalendar.currentCalendar()
  let components = NSDateComponents()
  let dateArray = matchesForRegexInText("[0-9][0-9]", text: date)
  components.day = Int(dateArray[0])!
  components.month = Int(dateArray[1])!
  components.year = Int(dateArray[2])!
     
  let actualDate = calendar.dateFromComponents(components)
  return actualDate!

So now you that you have the correct date with the correct timezone. So then you can use the differenceBetweenDate method to get the difference without any unpredictable bugs.

This may be a roundabout brittle way to do things. I’m open to a better way of doing it…please.

Ruby, Ruby on Rails

Wherefore Art Thou Method?

I’ve been learning me some iOS lately, the most striking feature is the IDE, coming from Ruby and my trusty text editor, IDEs were kind of a shock. It kinda felt like someone always looking over my shoulder. Constantly pointing out what I did wrong, sometimes while in the middle of typing.

After a while I grew quite fond of Xcode, I like how you could option-click a method and see what it was all about, or at least where it was defined.

Ruby doesn’t have anything like that, at least not in the text editor. And what with its plethora of gems, its kinda hard sometimes to find where a method comes from.

I encountered a something like this earlier this week when I was trying to understand some code that was written by another developer.

The app was using  Clearance, which is a pretty nifty authentication gem. So obviously an authentication gem would need a method called “authenticate” right?  I got confused though when I saw it was used like this:

 @user = authenticate(params)

However, when I tried to use it like this:

 User.authenticate(params)

I got a

ArgumentError: wrong number of arguments (given 1, expected 2)

That was weird, looking into the Clearance gem source code, I found this in authentication.rb :

  def authenticate(params)
        Clearance.configuration.user_model.authenticate(
          params[:session][:email], params[:session][:password]
        )
      end

So obviously it accepts one argument right? Maybe another authenticate method was defined somewhere else. After hours of intense research and/or googling around for a bit, I found a method in Ruby called source_location

What this does is it tells you where a method is defined. So running this line in the rails console :

 User.method(:authenticate).source_location

will return this line:

 ["/Users/farisroslan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/clearance-1.10.1/lib/clearance/user.rb", 19]

So it turns that there was another authenticate method defined in user.rb!

 def authenticate(email, password)
        if user = find_by_normalized_email(email)
          if password.present? && user.authenticated?(password)
            return user
          end
        end
      end

So now modifying my authenticate method for User so it looks like this:

 User.authenticate(session_params[:email],session_params[:password])

It worked well.

Now in hindsight, perhaps searching “authenticate” in the Clearance repo would have probably be quicker.Still, it should be useful if the other method is in another gem or library.

Uncategorized

Making Devise Mailers asynchronous

Devise is an awesome gem, it makes authentication for Rails apps really simple. One problem I faced was trying to make Devise mailers asynchronous. This kinda sorta worked, sometimes emails from devise will come almost immediately, sometimes it won’t come at all. Obviously, inconsistency is Not Good.

I figured the devise-async gem was to blame for this. So I decided to dive into it and see what I could find. Code reading is supposed to make you smarter anyway.

First thing I did was fork the gem, that way a copy appears on my github for me to modify and use. To use my own version of the gem I write this in my gemfile:

gem 'devise-async', git: "git://github.com/hewrin/devise-async.git"

With “hewrin” being my username.

Looking at tests are a good way to find out what a gem/app does. Unfortunately nobody told me about this when I first began diving in. All I did was insert “byebug” everywhere and send a devise email. But first, lets look at the Big Picture.

devise-async is a small gem, all the important stuff happens in the lib folder. To be more specific, the important stuff happens in the devise folder in the lib folder. Lets first look at the async.rb file.

From what I understand, this file is extending the Devise module by adding the Async feature. The file is pretty well commented, so its pretty simple to figure out what it does. The only interesting thing I found was mattr_accessor

mattr_accessor is like attr_accessor, difference is it creates getter/setter methods for modules instead of instances. This makes it easy for people to modify things in the initializers folder in a Rails app. The setup method at the bottom is what allows users to modify the configuration of the gem.

    def self.setup
      yield self
    end

I haven’t encountered this before, it seems doing yield self loads up the whole Module, allowing us access to all mattr_accessor .

The kind people who created the gem even gave us an example:

    Devise::Async.setup do |config|
      config.backend = :sidekiq
      config.queue   = :default
    end

In the example above, config.backend pretty much means Devise::Async.backend. So putting the above in a file in my initializers folder will set Sidekiq as my backend and the queue name as default.

Finally, at the bottom there is a method that adds the Async module to devise, this is what allows us to add devise :async in our model files to make the mailers asynchronous, just like when we add :confirmable to send confirmation emails.

The Devise.add_module method is quite interesting. Below is the source code of the method, taken from Devise:

    def self.add_module(m)
      class_eval <<-METHOD, __FILE__, __LINE__ + 1
        def #{m}?
          self.modules.include?(:#{m})
        end
      METHOD
    end

This…will be discussed in my next post.

Uncategorized

Seeding Stuff

Creating a new app is really fun. Whats not so fun is having to populate the database with dummy data so you can test how things work. Even more not fun is when changes happen (yes its true, requirements sometimes change, I’ve actually seen it with my own eyes) and you have to drop the database and repopulate it again.

Thankfully, Rails has the db:seed rake task. All you have to do is modify the seed.rb file in the db folder.

There are plenty of ways to do this:
(1) Using code

     [
      { :meal => 'Lunch', :price => 450.00},
      { :meal => 'Dinner', :price => 450.00}
     ].each do |c|
      Price.create!(:meal => c[:meal], :price => c[:price])
     end

This takes a hash and creates two Price objects. I think arrays would work just as well.

(2) Using CSV

require 'csv'
CSV.foreach("config/languages.csv", { encoding: "UTF-8", headers: true,header_converters: :symbol, converters: :all}) do |row|
   Language.create!(row.to_hash)
end

This takes a CSV file, in this case stored in the config folder.

headers: true makes the first row of the CSV file (in this case “name”) as the header. What this means can be shown below:

 CSV.foreach("config/languages.csv", { headers: true }) do |row| print row.to_hash end

Wil produce

  {"name"=>"English"}{"name"=>"Danish"}{"name"=>"Mandarin Chinese"}
  {"name"=>"German"}{"name"=>"Afrikaans"}{"name"=>"Albaniana"}
  {"name"=>"Arabic"}{"name"=>"Arabic-French"}

header_converters: :symbol as its name suggests, makes the header into a symbol, I guess the default is a string

(3) Using text files

open("config/nationalities.txt") do |states|
  states.read.each_line do |national|
  name = national.chomp
  Nationality.create!(:name => name)
 end
end

Here we use a text file, with all the nationalities having their very own line.
So you might wonder, why is there a double block in here? The answer is when we open config/nationalities.txt it returns a File object.(In this case, called “states”)
So we have to create another block that reads each line of the file individually. Then we can safely create Nationality objects with each line.

There should be more ways to do it. These are just the ones I’ve found.

Uncategorized

Little Steps

Hmm, Ruby and Ruby on Rails breaks into so many branches, I can learn testing, I can learn threading, I can learn metaprogramming. So many books to read too. There is Practicing Rails, Rebuilding Rails and even Practical Object Oriented Design in Ruby. And I haven’t even fnished the Pickaxe book yet!

But, Javascript is really important! I need to learn the MEAN stack and fast! I also heard that ES6 is coming up soon, I gotta learn that as well. My CSS sucks, I have no front end skill. I can barely make a website desktop responsive, never mind mobile responsive. My frontend skills need levelling up, NOW.

I read an article that “Real Men Code in C”. C is the mother tounge of programming. I can’t call myself a programmer if I don’t know C. And whats this functional programming thing I keep hearing about? Haskell makes you smarter? Erlang is good for concurrency? 

Thats an accurate transcript of what goes on in my head when I’m trying to decide what to learn next. A few months ago I started allocating “learning time” a few hours a week to learn something new. This noble activity usually ends up with me web surfing something totally unrelated. Usually some obscure thing I found on Hacker News.

I admit its partly because I have focusing issues that date back to childhood. But its also because I have a fear of “missing out”. When I first started this web developer gig, I kept reading how “5 years from now, everything you know will be obsolete” or “You must be continuosly learning”. I guess that spooked me into thinking I wasn’t learning things fast enough and that I should be mastering more complex (i.e incomprehensible) subjects. I have this weird habit where if the subject is so hard that I’m lost after the first paragraph, then I think it MUST be useful

After realizing that I’ve clocked about 50 “learning time” hours and haven’t actually learned anything, I’ve started to reassess my choice of topics. Instead of looking a one big topic like CONCURRENCY, I now try to master little topics. like maybe how partials work in Rails. I also liked the technique taught in Practicing Rails. The Tiny Apps method, where you create a tiny app to try new gems or a new feature first. Its awesome when you can test something out almost immediately. Especially for someone like me who can get distracted by literally anything.

I guess the point is to break everything into the smallest piece possible. Don’t make grand plans to study everything about Javascript for two hours, focus on sitting down to learn one specific thing for 10 minutes. I usually find myself pushing forward after those ten minutes to learn something else although there were plenty of times where I immediately stopped to do something else. Thats fine though, getting 10 minutes of learning time a day is 10 minutes more than I got previously.

 Don’t worry about getting good now, take your time. Small steady progress is better than giant steps that end up not happening . As a wise man once said, “How do you eat an elephant? One bite at a time”

Uncategorized

10 more things I learned working at a Dev Shop

Continuing from my previous post, I’ll be listing 10 more thing I learned from working at Web Development Company. Whats that? I only could do 3 last time but I’m shooting for 10 now? Like most things I do, there is a method to the madness. I read “Choose Yourself” by James Altucher the other day. One of his many many tips is to exercise your brain. You do this by listing 10 ideas on anything everyday. He notes that anyone can do 4 or 5, but 10 “makes the brain sweat”

I’ve been doing this practice for the past week, and boy has it tired out my brain. Doing it on an empty stomach does not help. One thing to note before I start, he warned in the book that your ideas will be horrible at first, they only get really good in 6 months or so. So if you find my list stupid, thats why.

So lets get sweaty!

1) Things always go wrong. I touched on this in my last post. Every time I pushed code into production, I’ll spend many many minutes (hours) frantically repairing stuff. Sometimes while the client was checking the website out. I wasn’t smart enough to write tests from the beginning. Learning to write tests is definitely on my to-do list.

2) Funny I mentioned to-do lists, cause my next point is about them. I don’t think I get the same benefit from to-do lists as other people seem to do. I’ll write things down on a piece of paper and promptly forget about it. Or I’ll write too many things, can’t decide which one to do and do nothing. I’ve started replacing my to-do list with a To-Do Thing. Where I usually just choose ONE important thing to do. Once I finish that. I create a new To-Do Thing. This has a bad side though. Sometimes after completing my Big Thing, I coast for the rest of the day. Usually when its almost 5 and I’m out of juice. So like all time managing/productivity techniques, the best time to do this is “it depends”

3) Documentation in software could really use some upgrading. I’m not sure if its because I lack intelligence or they did a half assed job. I bet its the former. Whatever, it would be nice if popular API’s had good,easy to follow examples. That there is a niche an aspiring blogger can fill…..

4) Making things simple is way harder then it sounds. I can’t remember the number of times I’d try explain something to my coding partner and he’ll just say “whaaaat?” Its true explaining things in a coherent manner isn’t one of my strong suits. One thing I’ve tried to do is to start from the very beginning. After that, while speaking slowly, build on that and explain the next point. Metaphors should only be used when you have the listeners full attention. That is pretty rare in this day and age.

5) Requirements gathering is really important. I know this sounds obvious, but its worth repeating, Really Important. In the Pragmatic Programmers, they talk about contracts and how they “protect” both sides. All I can add to that is yes. Make sure all requirements are gathered and agreed upon. Its also a really good idea to show stuff frequently to the client. At least keep them in the loop. That way they feel less anxiety (hopefully) and they can point out mistakes or modifications early

6) Keeping with the topic of clients, I got to learn to talk to them better. I need to learn laymans language. Whenever I said something I could tell it was too technical for them, but I couldn’t help myself. This ties up with point 4, it’s probably a level above. If you can explain things simply to a client in a way they can understand, then you should have no problems speaking to a co-worker.

7) Front-end is hard. I’ve always loved doing back-end development. Working on cool data structures and algorithms. I thought it was challenging enough. Little did I know the horrors of front-end, when the client gives you feedback saying “button not green enough”. I’m sitting there thinking “There’s more than one green?”. I admit I lack aesthetic sense. I can barely differentiate between a color and light of a specific wavelength entering my eye. I have to say though. I’m fascinated by how certain designs can make people “feel things”. If its true, its borderline mind control. Like I watched a designer working on a logo. And the client was like ” I want this logo to make people feel this and that and this…..”. I was gobsmacked. I mean, I’ve heard about “A picture tells a thousand words”, I didn’t think it was literally true!

8) Do learning on your own time. I noticed I didn’t have much time to learn much while working, usually cause we were chasing a deadline or two. Although I’ve done plenty of things on the job, I  didn’t spend lots of time really getting to know it deeply. There was always something new to create or fix. I’ve heard about how learning doesn’t happen much when you’re panicked and under pressure. And I’ve noticed the things I did didn’t “stick in the brain” much. I usually have to review what I did at night. Which come to think about it, that was what I did at the Bootcamp

9) Speaking of Bootcamps, mentors are priceless. To actually be able to learn from someone senior is a luxury unavailable in my workplace now. (Not the companies fault, its still new) So every so often we go back to the scene of our Bootcamp to hang out with the mentors and ask them questions. I noticed though, most of my problems, the ones that I really get stuck on. Are usually due to carelessness. A hidden typo, An uncapitalized letter, little things like that. Perhaps its less to do with mentors and more to do with my own carelessness. Having said that, its still pretty cool having someone you can go to for advice.

10) Which brings me to my last point. This has been bugging me for a while. We don’t really have much in the way of Best Practices in our team. We barely have Practices. Its more of a “Make Things Up As We Go Along” thing. I know Best Practices can be overused and are not applicable to every case. Still, it would be nice to have some guidance on what we do. If only to make the whole app consistent. One of these days my big To-Do Thing will be to create a list of Best Practices Guidelines. (Or even Better Practices Guidelines) Instead of the big ball of mud generator I have now.

Whew! 10 things! My brain is pretty sweaty right now. That was a good exercise though. It was pretty fun too. Until next time