As curricula changes, what's falling through the cracks?


Just a brief note to clarify a couple of things. As indicated in the comments, this post isn't about what's appropriate for HS CS. It's more about what kids have after they finish their education - be it high school, college, code school, or other.

Some of my thoughts are the results of pondering on the exacerbations of friends after interviewing people for entry level positions.

The two examples are just to illustrate the point.

Original Post:

I enjoy reading blogs. It's one of the ways I keep current. Not only in terms of what's going on in CS Education, but also trends in CS - academic or professional as well as on a range of other topics.

One of the blogs I enjoy is authored by Julia Evans. I don't know Julia, but we do have some mutual friends. I've enjoyed her blog. She does a nice job talking about any number of systems related issue. I've tried to leave comments a few times but for some reason, my comments always end up deleted or otherwise not showing up.

One recent post, one on concurrency got me thinking. Since the comment I left there didn't take, I thought I'd write about it here.

It's a nice post but the thing that caught my eye was when Julia said that she " didn't know what a semaphore was until I read this code and I was like OH THIS IS AMAZING AND SO USEFUL AND WOW." I was a little surprised, semaphores seem to be one of those basic concepts that you just know but that is, of course incorrect. I first learned about semaphores in my honors Systems class with my mentor, the late Robert Dewar. We started from test and set and worked our way up. I had two other undergraduate classes that at least mentioned the topic.

Then again, I knew that many undergrads would never get a good treatment of concurrency so I tried to build a bit in to the System Level Programming course I designed while at Stuy.

This got me thinking - according to her linked in, Julia was a CS major at McGill - a university that I hold in high regard but either semaphores were never covered or their treatment didn't make enough of an impact to be worth remembering. What topics do we cover in our classes that kids just let fall to the wayside and what topics do we end up losing as curricula change and we don't have an eye on the big picture.

One big one is memory management. When APCS and college 101 classes went to Java, memory management went out the window. Not a problem, as long as memory issues are covered in some other course. Unfortunately the don't seem to be. You can make a case that kids don't need to understand memory management or anything about garbage collection but I'd argue that while one might never have to do their own memory management a good CS person should have some understanding of what's going on under the hood or as my friend Gerry says "never use a technology you couldn't write yourself."

Another biggie that I lived through was the IBM PC era. Prior to the mid to late 80's when the IBM PC ruled the world, kids learned about CS on timesharing systems. Once the PC took hold, every kid learning programming or studying CS was working on their own machine. They had full access to everything and the machine just supported a single thread.

On the one hand, it was nice since you could easily play with low level programming and hardware but on the other hand, a hole generation didn't learn about the complexities of multiple users and multiple processes.

Early in my career I designed courses and only later did I realize that you can't just design a course, you have to look at the full arc of a students education.

I think it's interesting to think about what concepts are getting left on the side of the road and I wonder if the big players driving CS education spend any time thinking about this bigger picture.

NYC DOE - Doing what it can to keep opportunities away from kids

The difficulties I've had with the city and DOE are pretty well documented by now.

Today I'm going to tell you about my latest dealings with DOE and how they prevented my team from bringing free quality CS education to city students.

CSTUY's not running SHIP, its summer program this year.

That's not something I'm happy about but part of me knew it might happen. What did surprise me, although it shouldn't have, was the role that the NYC DOE played in preventing it from happening.

The bottom line initial reason for us not running SHIP this summer was my time. Moving over to my new position at Hunter has been terrific but I haven't had the time needed for adequate fundraising and outreach.

I recently talked a bit about the difficulties we've had with fundraising as compared to the "chosen programs" in this post.

I've also written a bit about related issues in these posts:

In any event, we weren't going to be able to run this summer.

When I spoke to the team, Sam asked, "if we can keep the budget down and figure out how to not be dependent on fundraising and outreach, can we do something?" I told him, I'd love to.

He came up with a plan. Instead of a full day program, we'd run half day - this means fewer staff hours and no lunch. If we could run it at Stuyvesant, in the computer labs (which already run Linux), we wouldn't have to worry about equipment.

Under this plan, additional fundraising wasn't needed, in fact, kids could attend free of charge.

In terms of outreach, since we already had sufficient funds, even if we only got returning shipmates and a few from word of mouth we'd be ok and if we could cast a wider net, so much the better.

Oh, and the plan was for me to take the summer off. I'd help with initial organization but I wouldn't actually work the summer.

So, to summarize:

  • Free for the kids
  • I'm not involved and receive no compensation for the summer (this is important for later)
  • My teachers would be paid for teaching in the program and CSTUY would supply the funds to pay them.

We floated the idea to Stuyvesant's principal figuring that since the teaching staff is from there and some of the kids tat would benefit are Stuy students it wouldn't be a problem. She said she loved the idea but had to send it off to the conflict of interests people.

You see, it's very important that teachers and former teachers don't actually benefit from working extra – it's critical that teachers be kept down.

Long story short - the teachers could work the program but aren't allowed to run it. They can come in and teach but can't talk to the principal about organizing it. For some reason, running a free program for kids instead of relaxing over the summer means that the teachers are getting this huge benefit. Sure they'd be paid for their time, but that seems fair.

As to me, I'm not allowed any dealings with the DOE for a year. Forget the fact that I wanted to set this up while taking no pay so that the kids wouldn't be left without a program. Nope, that's no good - can't have us bringing quality CS education to the kids.

I dealt with these folks once before so I wasn't really surprised.

A few years ago, a friend connected me with people at Amplify to see about creating their APCS MOOC. We met a couple of times but then the DOE people said I couldn't work with them even though I was just going to be working on the MOOC and not dealing directly with the DOE in any way. I wasn't negotiating contracts, making sales pitches, or anything. I was just going to work on MOOC content.

It wasn't like a certain NYC School's Chancellor who had just left the DOE and took the leadership position at Amplify. That wasn't a conflict - I guess it's just important to keep the teachers in line - the rules aren't meant for the higher ups.

Funny side note – when I shared the fact that I couldn't work for Amplify with my friend, his first reaction was "because of the union?" That seems to be the knee-jerk reaction from people in the business world. Nope - the union was fine with it - it was the administration / city. The city has done far more harm to the public schools than the union ever could. Pretty much all the union does is make sure the city follows the jointly negotiated contract.

Back to the story.

So, we're not allowed to use school space to bring free CS education to kids this summer. Plenty of other organizations non-profit and for-profit alike seem to have no problem bringing their programs into the schools. I'm sure many are getting money for this, grant based or otherwise. In all cases, I'd take my team and their program over what the DOE is actually rolling out.

This is the type of thing makes me want to say to hell with DOE but, unfortunately, they aren't affected, it's the kids that lose out.

Awards for Educators

There are all sorts of awards for teachers. The Presidential awards, NEA awards, National and State level awards, and more. There are also awards and honors given in more narrow areas like NCTM for math and our own ACM.

I've haven't won any and never expected to. I've never played well with the establishment.

It's ok though. For every honoree that I can point to and say "there's a master teacher," there are half a dozen who you look at just know that it was more about politics and connections than about teaching chops.

Like anyone else, though, I do like a pat on the back and it is nice to get some confirmation that you're having a positive effect on kids lives.

So what are my awards? Well, I received what I consider my highest honor this past weekend. I was in Hot Springs Arkansas for Jen and Marcel's wedding.

It was a great weekend with old friends and new celerbrating a wonderful event and I couldn't be happier for the couple.

As a teacher, to be included in your former students life events is as big as it gets. I can't begin to say how honored I was to be included in their day. Even more special, that Marcel's brother Barnabas and his wife Suki are my oldest couple - they started dating back in my class back in the beginning.

It's not the first time I've been invited to former students weddings. I've seen around a dozen or so of my students wed. Every time it's special, just as it's special when a former student decides to reach out to let me know how they're doing or to reconnect in general. When they elect to share part of their lives with me, it tells me that I was at least a little bit of a force for good way back when.

Become a CS Education Thought Leader - No Experience Needed

A few weeks ago, a friend asked if I knew any CS teachers that were available to work this summer. At the time, I didn't have anyone to recommend. We were still up in the air on running CSTUY's SHIP summer immersion program.

We ultimately decided not to run SHIP this summer. Mostly due to the fact that in my new position, I didn't have the time to do the necessary fund-raising and outreach. We're continuing with our Saturday program through mid May and plan to bring more opportunities to the kids of New York City in the future.

That's not what I want to write about today. That summer program looking for a teacher, let's call it program X made me think about many of the players driving K12 CS education both in NY and beyond.

It turns out, the people that were running program X didn't have a teacher, didn't have curriculum or program, and in fact didn't have a plan. What they were able to do, however, was raise money.

This is a sore spot with me - for CSTUY, we run program to program and for me, fund-raising is the hardest part. Here we have a program that has no idea as to what they're going to do or who's going to do it and they ended up with substantial capital to work this non-existent program.

It's a sore spot because I've seen it before and seen it over and over. People with either little or no CS experience, little or no teaching experience and frequently neither being anointed as thought leaders in CS Education or at the very least, the people with the "hot program."

I've seen this in companies, non-profits, for-profits, and government. Some of these groups and programs are now considered undisputed leaders when, if you dig beneath the hype, they really don't know what they're doing.

Now, there are some "thought leaders" who have been in the trenches and know their stuff but they seem few and far between.

I know that all of these people running these programs and being given this platform to influence our young are well meaning and I welcome everybody to the table but maybe, just maybe they should take a step back and ask themselves - do they really know what they're doing or are the just experimenting with other peoples children.

Blogging with Emacs, Jekyll and Nikola

Switched over from Jekyll to Nikola yesterday.

One of the primary reasons was that I got fed up with managing a Ruby development environment across all my machines. In spite of my rantings, I'm sure Ruby and Ruby installs are fine - it's just something that I'd have to deal with on a recurring basis for one specific task - other than for Jekyll blogging, I don't use Ruby.

So while a platform based on Python - generally my go to language, made sense, the other driving force for the switch was the fact that Emacs and org-mode have become such major parts of my workflow and productivity.

What do I use org-mode for?

  • lesson planning
  • document preparation (instead of LaTeX)
  • note taking
  • blogging
  • email (with mu4e)
  • managing my schedule
  • tracking bookmarks

and probably a lot more.

Jekyll is actually a really nice tool. It's simple. You put together a simple directory structure: Templates in _layouts, blog posts in _posts, drafts in _drafts. Other directories that start with an underscore are ignored and everything else is copied up to your site.

I love that it's "close to the metal" You can put in html files with some meta information up top or markdown.

You can take a look at my old site at if you want to take a look.

The beauty is that you just push your files up to GitHub and it automatically runs Jekyll and builds your site (more info here).

The problem is that Jekyll doesn't play well with org-mode and org-markup so my workflow became something like this

  1. Create a post in the _org directory.
  2. From within emacs, publish it. I've configured org-mode to publish by exporting the org-mode markup file to html and saving it in the _drafts directory.
  3. If it looks good, copy and rename the file from _drafts to the _posts directory and push it up to GitHub.

A little clunky, but it works. The bigger problem was the amount of time I'd spend putting html blocks into my org formatted posts to get them to look the way I wanted (or at least close enough).

Enter Nikola.

Nikola's a much more powerful tool. It does much more but as a result is much more complex. Normally, that's not my style but in this case since It's Python, things balance out.

I still have to figure out the entire templating system and all the plugins but getting started was pretty quick.

The big win is that Nikola supports a ton of formats for your posts and pages. Native org-mode support for me was what did it for me. On top of that, although I haven't tested it yet, is that there's also an org-mode plugin to export to Nikola restructure text.

My new workflow:

  1. Write the post as an org-mode file.
  2. run nikola github_deploy.

And that's it. You can look at my Nikola site here: The source code is in the src branch, the actual rendered blog in the master branch.

So far, I'm pretty happy with the setup.

I hate ruby or why I'm switching blogging platforms

I think I've got the move worked out but if you're reading this via an rss or atom reader, make sure to check back in a couple of days - you might have to re-subscribe.

Why am I switching?

Because I hate Ruby.

Ok, not really - I barely know the language. I was already a Python guy when Ruby came along and I didn't see any real added value to switching.

This isn't really about Ruby though, it's really about how that which we don't know is strange and frightening. In this case, the ruby ecosystem.

I started using Jekyll because that's what was supported by GitHub pages. It's fairly simple and it basically worked. It had a few warts, specifically, I've had problems getting org-mode blog posts to publish just the way I'd like and it's hard to debug when a post has some bad markup in it, but it got the job done.

Recently, though, I've had to re-install Jekyll a number of times and for me, that's been a nightmare.

One is supposed to just be able to sudo gem install jekyll.

Ok, so you need some packages installed:

sudo apt-get install ruby-dev

But I've got ruby 1.9 and I need ruby 2 point something. Ok:

sudo apt-get install ruby2.0 ruby2.0-dev

But that fails since we're still running 1.9. Every time I look for a solution I go down the ruby ecosystem rabbit hole.

All I want is Jekyll!!!!!!

Why can't I just pip install jekyll like I can do with Python packages!!!!!

In truth, there's nothing wrong with the ruby ecosystem, It's just something I'm not familiar with. I probably had to go through the same battles with Python it's just that I did them incrementally over time.

The truth is, setting up a development environment should be much easier. It used to be that I installed Linux, it had C installed and I just had to install make. Now it's all about tool chains, virtual environments, containers, and more.

I think this is what Roy was talking about when we traded tweets on using development environments in an Ide or in the cloud.

If it's hard for me to get an environment running, imagine some poor soul who just went through a "learn to code" web site and now has to figure out how to set up his or her own machine!!!!!!

I don't have a solution but at least it hasn't stopped me and others from trying new things.

Two of my CS blogging friends, Garth Flint and Alfred Thompson have in their own ways talked about this same issue. Garth, showing a bias towards VB yet still working to get his head around Python. Alfred shows the same disdain for Linux and the command line as I show towards Windows. All this leads to valuable learning experiences and discussions.

Personally, I'm also going through this battle as I continue to explore Clojure.

So, I'm going to finish the changeover to Nikola in the next day or two. Remember to check back in case the feeds aren't working.

Once I make the change, I'll talk about Jekyll vs Nikola as actual blogging platforms.

IDE or the Cloud

This weekend, I had a conversation on Twitter with my friend Roy Bahat:

Another friend had just asked me about IDEs vs local installs for learning enviromnents the day before.

So, should we use cloud based IDEs when teaching CS or should we use local installs.

There isn't a single right answer but I thought I'd share some of my thoughts here.

I'm hoping this is helpful to both those of us in the trenches as well as maybe some platform developers out there.

Some times, you don't have a choice.

On the web based side, does your school have the bandwidth. We're not only talking about the pipe to the outside world but also wifi within the school. If kids can't reliably get to the web based environment, it's not a viable option. On the other hand, cloud based software will always be up to date and properly configured and kids can use them from home or pretty much anywhere they have a connection.

On the other side we have local installs. This can also present problems. Is the teacher allowed to install locally? Does he or she know how to do it? Who's going keep all the machines up to date and configured?

Assuming we can get past the technical issues we can start looking at the education side of thing.

On the web based side, you've got a silo. This can be both good and bad. In an intro class, using a tool like Codesters can keep the cost of entry low, allow students to share work online and allow teachers to make use of their curricular materials. If you can't tell, I'm a big fan of Codesters and the Codesters team. The limitation is that you have to use their simplified interface and toolset.

Some web based IDEs like Koding offer more flexibility - one tool with many languages as well as deployment. The cost is complexity. With Koding, you're basically running a virtual machine in the cloud. You've got their web based IDE and a terminal shell so it's not as complex as doign everything from scratch locally but it's not as structured as Codesters and is more of a general purpose site rather than one focussed soley on learning.

Then you have This looks to be a great platform for experienced programmers to play with and explore new languages but I'd be concerned about using it with beginners. It looks like they're rolling out some teacher tools so this might be worth revisiting soon.

In any case and with other web based products, you're living in the providers silo.

Personally, I'm a command line wonk and confessed Emacs geek so I'm generally wary of an online environment without an exit strategy to real world tools. Eventually, if all development moves into the browser as platform then this problem goes away, but for now, you're not going to have the expressive power and flexibility that a local install gives.

Local installs let you use more powerful and flexible tools either alone or in combination.

Keeping kids out of silos also makes it easier for them to learn new tools, languages, and techniques.

Since I like generic tools, I'm not a fan of big professional IDEs like Eclipse. I'm an Emacs geek but Atom, Sublime Text, and Vim are all good as well.

There are also an assortment of beginner IDEs like Dr. Racket and I'm a fan with these for beginners as long as there's an exit strategy.

For completeness, I should mention that if I weren't an old school Emacs guy, I might check out something like JetBrain's IDEs. They're much lighter weight than something like Eclipse but still full featured. Somewhere between a true general purpose, customizable, programmable editor and an all encompassing IDE.

In general, I use online enviromnents with my classes early on when:

  • They're pretty much identical or equivalent to the installed version.
  • They provide some value added (codingbat for example) so they're not being used as a development environment but for some other purpose.
  • They help with student collaboration (such as cloud9 or for more advanced kids).

In any case, it's imporant that our kids aren't locked into any IDE be it web based or local.

Our kids that go on to more advanced CS studies will certainly need to break out of sheltered world of a learning IDE and we're not doing them a service if we shelter them too long.

Our other kids also benefit from seeing beyond these restrictive environments. A student might learn to code in Python in one of our classes, but if we do our jobs right, that student might be writing a little Javascript to automate Google Docs.

I can't tell you how many people I've seen go through online coding courses in a web based enviromnent only to be unable to do anything outside of that enviromnent.

At the end of the day, we want our kids to be empowered to grow on their own. All of the things I've talked about here are merely tools. Each has it's place. It's up to the teacher to make the roadmap and to lead the student down the path.

Hunter College - Honors CS

It's been a while since my last post and a while since I started at Hunter.

Time to share a bit about what I've been up to.

One of the better kept secrets in New York City is Hunter College's computer science program. It's been around for years and it's been that way for years. In fact, when I was looking to get my masters degree back in the mid nineties I carefully researched all of the area's MS in CS programs. It came down to Hunter College and Courant Institute at NYU. I was going to go with Hunter since the programs seemed comparable and Hunter was far more affordable but I had to go with NYU due to class schedules. Too many of the Hunter offerings were to early in the day and I had my full time teaching job to consider.

Hunter isn't currently offering their Masters program but their Bachelor of Arts program is alive and well, it's just that people don't know about it.

Part of my job is to change that.

Well, not really, part of my job is to add my piece to the puzzle. The rest will take care of itself.

My piece? It's all about creating a tech culture, tying into the NY Tech ecosystem, and filling in the gaps that are shared by just about every college computer science program.

How do we do it?

The long term plan is that we're starting a new CS Honors program. In the fall, I'll be teaching and mentoring a group of entering undergrads. We'll have workshops, trips, activities. You name it. I'll also be teaching them modified versions of our courses with the hope of bringing some of my modifications back to the rest of the student body. Things like integrating real tools and professional techniques into what is already a solid academic program.

In the mean time, I'm getting to know Hunter's current CS students and working to energize the existing community.

We already had an amazing event hosted at Yext. We had a panel and mixer with representatives from about a dozen companies talking to the kids about the possibilities ahead of them.

We've also set up a couple of workshops in house.

I'm also starting to talk to friends at companies across the city to plan out both curriculum and programs to set up our kids to succeed.

My goal is that within five years, I want people to realize that Hunter CS is the place to be for CS Education in NYC. Not everyone can afford the 40K and up private college tuition and there's no reason to when you can get a great CS education with ties to the tech community at CUNY prices.

If you want to help, drop me a note. We're looking to start something very special and you have a chance to be a part of it.

DevOps, or You don't know what the F you're doing!

Having just concluded almost a quarter century at one job in one place, I've been reflecting on a number of things.

What I accomplished, what I've failed to accomplish, highlights, low lights and everything in between.

I've also learned a lot over these twenty five years.

One thing I learned is DevOps and System Administration.

Back around 1993 or 1994 Stuy wasn't really on the internet. Yes, we were able to scam even though we were a high school and yes we did have a class B address block but no one really had access.

Somehow, Bruce, a student of mine at the time and I ended up with the job of getting Stuy onto the internet. Bruce was one of our superstar kids and people thought I had extensive experience setting up and running networks. Truth be told I messed around a bit but there's no way I would have hired myself for the job.

Nonetheless, we were off.

We were able to take one of the RS/6000 AIX workstations that were supposed to be used as CAD stations and repurposed it as a server. We made email accounts for everyone and were off.

Neither Bruce nor I really knew what we were doing but we figured things out. I learned a lot from him and I'd like to think he also got some benefit out of working with me. Fortunately, we seemed to have a knack for finding the answers.

Of course, we had our moments. Once, we got a critical patch announcement from IBM. It said that if we needed the patch and didn't apply it were were in big trouble but if our machine didn't need it, applying the patch would kill our system. It was unclear whether we needed the patch or not.

After about a half hour research, we determined that we didn't need the patch.

But applied it anyway :-(.


After a brief set of panic attacks and a bunch of fumbling around, we did manage to restore things.

So, Bruce and I ran the system for a year or so and as I said, I learned a lot. Now, Bruce was close to graduating so I was starting to worry that I'd have to figure this all out myself soon. That was a seriously frightening thought.

I figured it would be good to bring in a couple of new super smart students. As it turns out, Jon was one of them.

At one point, there was some problem and Bruce and I were going to head to the office to try to figure it out. Jon asked if he could come and watch. I thought that was a great idea so I agreed.

We all went to the office and Bruce and I went to work. After about fifteen minutes, Jon blurted out:

"I just figured how you guys do it!!!"

"You guys have no idea what the F you're doing!!!!!"

We all cracked up.

He was absolutely right. We had no clue. We didn't know what we were doing but we had become pretty good at figuring things out.

Truth be told, that really is the norm. If you already knew how to solve the problem, well, then it really wouldn't have been a problem to begin with.

So, you learn to figure it out. It's something I learned not to be afraid of a long time ago. I hope that it's something I've been able to convey to my students.

Debugging deployment

SoftDev students are hard at work on their final projects. By now, they all have fairly complex code bases. This limits how much I can help them with debugging.

There are some problems, though, that they have to contend with that even with experience, are hard to spot. Notably because the very tools you use to debug these errors are part of the problem.

Last week, this happened twice. Both cases were brought to me by really strong students which just goes to underscore how insidious these problems can be.

Here's a fake code snippet of a Flask application that illustrates both problems.

 1: from flask import Flask, render_template
 3: app = Flask(__name__)
 5: @app.route("/")
 6: def index():
 7:     return "hello"
 9: @app.route('/test/<some_data>')
10: def test():
11:     picture_url = build_url(some_data)
12:     result = api_test(picture_url)
13:     do_something(result)
15: if __name__ == "__main__":
16:    app.debug = True
17:    app.secret_key = "some secret key"
18:"", port=8000)

First, the "easy" one. The student was trying to deploy the application. We use Green Unicorn to deploy our applications, ultimately on Digital Ocean servers in the cloud.

The student was using the correct command:

gunicorn -W 4 -b app:app

but it wasn't working. It ran, but whenever he went to the site, it came back with an error.

The problem?

He had to change:

if __name__ == "__main__":
   app.debug = True
   app.secret_key = "some secret key""", port=8000)


app.secret_key = "some secret key"
if __name__ == "__main__":
    app.debug = True"", port=8000)

Normally, when developing and testing our applications, we use the test server that's bundled with Flask. The line that reads "…" takes care of this.

When running the application as a "main program" - "python" the if statement is true and it runs the indented lines, setting the secret key which is required for session management.

When running under gunicorn, the gunicorn server loads the application as a module and then runs it. In this case name isn't main so it never sets secret key and so we have a problem.

Pretty subtle and even though we did cover this in class, it comes up pretty rarely so it's not an easy catch.

Then there was this problem.

The setup for this one's a little more complicated. The group was using a facial recognition api. You provide the API with the url to an image, it fetches it and does recognition.

It's also important to note that when Flask is running, it will serve files from a static directory, so, if I'm running my flask server on myhost, port 800 and you stored an image named picture.jpg in the static directory, going to:


would get that image.

The group did things right. They ran the Flask test server to serve the static files and then wrote a small python program to test the api:

picture_url = build_url(some_data)
result = api_test(picture_url)

Everything worked fine.

But, when they put this code in as a route in their web app (as in the top code fragment), it froze.

They couldn't figure it out.

The code worked as a "stand alone" but not in the web app.

The problem?

Once again, the built in Flask development server.

The development server runs in a single thread / process. This means it can only do one thing at a time. When they ran their test as a separate program, the api they used made a request to their app to serve up the static picture file and it worked.

When they ran from the Flask application itself, their app made a call to the web api (line 12) and then blocked while waiting for the response. The web api tried to request the image from the Flask app but it was blocked – deadlock.

Again, the solution was to run the web app using a server that could handle multiple requests - gunicorn.

Once again, that solved the problem.

Both of these problems were fairly subtle and very hard to catch - even with experience. I remember the hours I lost when I was learning this stuff.

Some times kids get caught up in algorithms or poor code design but sometimes, it's just the tools.

Enter your email address:

Delivered by FeedBurner

Google Analytics Alternative