Tim Harvey :: Blog

Icon

I help organizations who feel stuck

PPL: Day 17 – Systems Part 2

This is part of the Peer Pressure Learning 30 series. Jump to my introduction to the experiment if you got here from Google or some other site.

Several mornings this past week were taken up by building http://ervscafe.com/ with Vince. We did the site for free to help out the restaurant painfully stuffed into the 7th floor of our building. We love having Erv (his real name is Kevin) around to feed us. It’s a pretty ghetto site, but the idea was quick and dirty.

With that pretty well done (I need to do a bit to the Rails app so he can update his specials), I’m back to having a bit more time for PPL. Hopefully tonight will be my last weekday post done in the evening for a while.

Today’s reading: pg 164 – pg 170

While this chapter continued with a bunch of Java-specific framework details (Swing, JBoss, Beans, etc), one particular concept leapt off the page and seemed to have a potential impact on a large Rails app:

In Spring, you write your business logic as Plain-Old Java Objects. POJOs are purely focused on their domain. They have no dependencies on enterprise frameworks (or any other domains). Hence, they are conceptually simpler and easier to test drive.

Whoa! Can you imagine an entire Rails app that used Models as data containers and plain Ruby classes to hold all the business logic? It frightens be rather a lot, but the idea that all that business logic could be more easily transferred to another language, a different framework, or more easily modified sounds incredible. Separating persistence (and framework crap) from business logic sounds like win to me.

Downside? That seems to fight against much of the Rails conventions and common practice, so implementing a solution in that manner would require treading very rough, new territory.

I have a small portion of an app I did constructed somewhat this way. I’ve been wanting to write up a blog post on the topic as it’s a pretty in-depth implementation. This chapter gives me hope that I just might have been onto something purely by chance!

Another great standout from the chapter is the discussion of decision making. This nails it:

We often forget that it is also best to postpone decisions until the last possible moment. This isn’t lazy or irresponsible; it lets us make informed choices with the best possible information.

And finally, the best bit of all:

…never forget to use the simplest thing that can possibly work.

Well said.

Next up? Emergence. Again, I have no idea what that means, but it sounds impressive (it has to be, the word has 3 syllables).

Miles continues to bang out his PPL blog posts. His latest is on the Python framework Django (pronounced, “JANG-go”, I think).

Google: Please update the site i built

Dear Google,

Your index is out of date and I’d love for you to revisit this site ASAP: http://factsandfiguresscotland.com/. Kthx.

Tim

PPL: Day 16 – Systems Part 1

This is part of the Peer Pressure Learning 30 series. Take a gander at my introduction to the experiment.

Ok, I’m back on track with two blog posts today. My Day 15b – Classes Part 2 post fills in the gap left by my Day 15- FAIL.

I started into the rather heavy chapter on systems. It’s a higher level look at clean code from the architecture and strategy perspective. A ton of it was either over my head (and heavy into Java) or was tough to apply with my Ruby on Rails goggles on.

Today’s reading: pg 153 – 163

Wow, this was some intense stuff. Uncle Bob talked about some interesting pitfalls with coupling the instantiation and management of dependencies in with the business logic. I could see a lot of validity to the problems that causes as you get into larger and large codebases. The pain of changing out your ORM already leads me to believe that Ruby on Rails projects likely suffer from some of the problems he talks about.

He shared some interesting examples of how to decouple the initialization of your objects from the run-time code, but I couldn’t even begin to understand how that would relate to a Rails app.

I have to take a cue from Miles to make any sense of this blog post:

What I Think I Now Know

Think, think, think before you go charging down a path with your classes. The author showed an example of the ubiquitous lazy-loading method of instantiating objects that I’ve used numerous times. In addition to pointing out that it may be a pre-mature optimization, he also explains that it can tie the instantiation too closely with your business logic. What does one do about that? I have no idea.

Realize that your toolkit or framework may fight against what you’re trying to accomplish. While I don’t know what you’d do about it, we have to realize that any framework we use was designed with a purpose or set of goals. Those may be different that we we need to accomplish with the current work at hand. I’m not suggesting that we throw out frameworks, merely that we understand their strengths and weaknesses. And at the same time, we learn to see clearly when it’s time to buck the convention or stick to it.

Finally, one must accept that you can’t architect any system for the needs you’ll have in 12-24 months. It’s just not going to work out exactly the way you expect. As believers in Agile, we need to accept change and do what supports today’s requirements with basic consideration for the future. We need to be wary of over-engineering.

PPL: Day 15b – Classes Part 2

This is part of the Peer Pressure Learning 30 series. Jump to my introduction to the experiment if you haven’t been following along.

Ok, it’s a day late, but I’m back on the wagon. It’s really day 16, but I’ll get back to that in a few moments. I need to play catch up first!

I have to make a brief digression. This Peer Pressure Learning has impacted a number of areas in my life. I’ve found that as I’ve been more focused and disciplined, other priorities have felt more effortless.

I’ve ridden my bike or walked to work almost two weeks now (with one or two breaks). That has paid off big-time for my soccer league. I’ve been a lot more effective on defense and logged my first assist today to bring us back from a 1-2 deficit. Geek fitness for the win! Ok, enough of that, back to the code!

I lucked out with today’s reading. The balance of the Classes chapter wasn’t particularly long. But, it was home to some great material about organizing your classes with an eye towards future change. It’s been said a thousand ways…and I’ll repeat it again here: the only thing in software you can be certain of is that you’ll have to change tomorrow what you wrote today.

Today’s reading: pg 147 – pg 152

I glossed over the Single Responsibility Principle of class design from the first portion of the text, but it was impossible to miss here. The idea is that a class with more than two responsibilities is a broken design. A couple ways to tell that one has broken the SRP (my paraphrasing from memory):

  • Describing the class in plain english includes words like “and”, “or”, “if”, or “unless”
  • Finding private methods that only support a few of the public methods or private variables used by a small portion of the methods
  • More than one type of application change will impact the class (meaning it’s probably doing more than one thing (see the first bullet)

It’s pretty genius. It leads to mountains of tiny classes. Coding this way must be a complete mind shift. One couldn’t do this haphazardly or you’d go crazy. Lots of tiny, but complex classes would be awful. You really would have to get darn good at simplification and organization. Thank goodness for tests, you’d have no way to complete a refactor otherwise!

A throw-in at the end talked about one of my favorite concepts (I like it, but probably am not that great at it): Separate stuff that appears likely to change from stuff that will stay constant. Don’t put them in the same class!

Why do you think we have configuration files full of application constants and don’t put that stuff into our classes? It’s partly to eliminate duplication, but just as importantly, it’s so our system can evolve through editing as few files as possible.

One of my other favorite testing methods was talked about as well. When you have to interface with some external class (one that’s perhaps complicated or an API), pass in the class as part of the initialization or using a setter method. That way, your tests can push in a mock object for easier validation. It also allows you to decouple your code from an external or volatile library. Nice!

Next up, Chapter 11: Systems (I have no idea what the chapter is about, but it sounds cool).

While I’ve been slacking, Miles has been tearing it up!

PPL: Day 15 – FAIL

Yea, I managed to blow it today. It’s 11:30 and I just can’t bring myself to stay up another 30 minutes.

I’ll probably look to pit through two posts in the next day or two.

I’m working with a friend to build a free web site for our building’s cafe, so tomorrow will be tough. Wish me luck!

PPL: Day 14 – Classes Part 1

This is part of the Peer Pressure Learning 30 series. The introduction to the experiment post will make all things clear.

Whew, I almost forgot tonight! That would have been my first miss. Luckily, after toying with the Facebook API and FQL for a while, it dawned on me that I needed to finish reading the chapter on Classes (which I started this morning) and blog!

Today’s reading: pg 135 – pg 146

Having read a chunk of Code Complete, thinking about clean, concise classes isn’t entirely new. I was pleased to find that Uncle Bob isn’t fanatical about perfection, sometimes bending the rules on privacy:

For us, tests rule. If a test in the same package needs to call a function or access a variable, we’ll make it protected…

Nice, that had been bothering me for a month or two. It seems that my larger classes end up with a private method or two that I’d like to test. They’re tested by virtue of the public methods being tested, but a targeted test would help at times. I didn’t like the idea of making them public, so this strikes a nice balance.

As with functions, the author makes it clean that they should be small, and then you should go back and make them smaller still. But…he makes a great distinction: “with functions we measured size by counting physical lines. With classes we use a different measure. We count responsibilities“. Oh man, genius!

Fighting with Rails

I’m clearly still new to Rails and find that the conventions seem to fight against the larger OOP concepts at times. I’m sure that as I get more comfortable with the plumbing (and hell, Ruby itself) that I’ll find all this easier. I read the following a struggle to know how to make such nice-sounding organization a reality in a world of “fat models”:

At the same time, many developers fear that a large number of small, single-purpose classes makes it more difficult to understand the bigger picture. They are concerned that they must navigate from class to class in order to figure out how a larger piece of work gets accomplished.


However, a system with many small classes has no more moving parts that a system with a few large classes. There is just as much to learn in the system with a few large classes. So the question is: Do you want your tools organized into toolboxes with many small drawers each containing well-defined and well-labeled components? Or do you want a few drawers you toss everything into?

It’s crazy stuff. While I like the idea of small drawers, I suspect that I would end up creating a ton of tiny drawers that don’t have the requisite organization. Time will tell!

PPL: Day 13 – Unit Tests

This is part of the Peer Pressure Learning 30 series. Get a handle on this PPL thing with my introduction to the experiment.

It’s the weekend, so I’m back to the evening groove. The morning was relaxed and the whole family and I went to visit the Amish farm that we buy all our meat, eggs, and chicken from. But that’s another blog post.

Today’s posts is on unit tests. I’m trying not to be a snob as the Ruby community seems to really have testing nailed. Between Rspec and Cucumber, I’m in heaven. I have to remind myself that there’s a lot to learn from the Java community and especially about writing good tests.

Today’s reading: pg 121 – pg 134

Uncle Bob seems to nail me with every chapter. I have been, for the most part, a self-taught programmer. The programming courses I took in college were a joke that I dominated in my sleep, so I jumped over to a business degree so I could learn something I didn’t know. But therein lies the problem. Until now, I’ve never had a systematic approach to polishing my craft. This line from the text describes me to a T:

…in the mad rush to add testing to our discipline, many programmers have missed some of the more subtle, and important, points of writing good tests.

Some really good points come out of the chapter:

  • Test code should match the code quality of production code – I can relate here…test code changes all the time as the requirements change. If your tests are crap, you’ll pay for it every time you have to rewrite tests. Changing over to using Factories has been a perfect example. The tests stay DRY and have been much easier to maintain since the change. Uncle Bob (the author) correctly says: “Test code is just as important as production code.”
  • Tests give you courage – That’s a weird thing to say, and it’s definitely my interpretation of the text. But…it really is true. I have tremendous faith in the test suites I use in each of my apps. Because of the safety net they provide, I can rename large models, change big chunks of logic, or refactor sections of tricky code without fear. My tests tell me when I’m done! I couldn’t go back to a non-TDD (test driven development) language ever again (or one with sucky TDD tools). I really mean that. I’d be hard as hell.
  • One assert per test…probably – I like that Uncle Bob feels free to break the rules. While it’s a good goal to shoot for one assert per test, the added code and duplication may negate the benefit. I find that I frequently pair a record count assert with an assertion about what’s in the record. The better guideline is to test one behavior (the text says, “concept”) per test.

All in all, I feel pretty good about where I stand with test code. I definitely need to hone my comfort level with the tools I use, particularly to reduce duplication.

I’m totally pumped about tomorrows reading which begins a journey into the depths of classes and their proper composition.

If you’re ready to melt your brain on some wild code stuff, read Miles’ post on Factor, a crazy weird stack language that’s unlike anything you’ve even seen.

PPL: Day 12 – Boundaries

This is part of the Peer Pressure Learning 30 series. The introduction to the experiment post will make all things clear.

Today’s already been a fun day. Vince, my partner in crime at the office, and I got up early and started banging out a free web site for our building’s cafe. It’s a great little restaurant on the seventh floor that needs some help with a bit of marketing. Look for http://ErvsCafe.com/ soon.

I also had a blast this morning reading about software boundaries. It’s a pretty important topic when you begin considering larger systems.

Today’s reading: pg 113 – pg 120

The general idea is that we need to manage how our code interacts with software written by someone else, or that might change frequently. It’s really another look at coupling.

Rather than sprinkling code all through our app that uses a particular gem, we’re encouraged to write a wrapper class so that it’s less disruptive (sorry Jerry). That way, we can swap out an uploader / asset gem with something else and don’t have to rewrite large swaths of the application’s code. This comment about such classes sums it up best:

It is able to evolve with very little impact on the rest of the application

There’s a wonderful gem in this chapter. The section on exploring and learning boundaries offers some excellent advice on getting used to and beginning to integrate a new library.

One of my big takeaways was the authors encouragement to write tests that exercise the new library. It forces you to begin learning the library’s API and documents your understanding. It also acts as a safety net when the library updates. You’ll know immediately if some portion of the API you are familiar with changes. These are the kind of test, in my world, that I’d leave for the CI server to run once they’re in place. There’s no sense in running them regularly unless you’re working with changing out that library.

Looking for some more PPL goodness? Take a peek at Miles’ Day 10 post on Erlang!

PPL: Day 11 – Error handling

This is part of the Peer Pressure Learning 30 series. Read my my introduction to the experiment to learn more.

After two days on Objects and Data Structures, I felt like I was beginning to get a better handle on the concepts. I’m pumped about today’s topic as I’ve just been pondering how to handle bad inputs (to libraries) and thinking about alerting (to me) of recoverable error conditions.

Today’s reading: pg 103 – pg 112

This statement kicks off the chapter on the right foot for me, setting the stage:

Error handling is important, but if it obscures the logic, it’s wrong.

Nice. Definitely not playing around on this topic! This was particularly valuable as the discussion turned to null values in arguments and return values.

Two critical sections were particularly timely for me, titled “Don’t return null” and “Don’t pass null”. I had really been struggling with this and as a result, been adding .nil? checks all over my code. I just had a conversation about it yesterday and was at a loss about what to do.

Now, it’s funny because I failed to take several things into account:

  • Rails already has some great error handling, so if a null creeps in somewhere, the user gets a nice error message and Hoptoad helpfully kicks me in the mouth with a nice shiny stack trace.
  • While it’s definitely worth coding defensively, my code is the only code that calls the methods I’m worried about, so I can trap for bad user input long before it gets into the libraries.
  • Throwing exceptions is not a bad practice. I read a blog post talking about bad usage of exceptions to control program flow and have since stayed away from them. Dumb. In several cases, I’d been returning nil as a flag that something had gone wrong and allowed the caller to deal with it. That’s pretty lame. Thinking now, I realize that I could define some sensible exceptions and allow the caller to handle each differently depending on the situation.

Chances are good that most of my .nil? checks are pointless and only satisfy test cases that I created in rspec. Boo. Time to rip some stuff out because as they say, “No code is better than no code.”

So…all that to say, there’s some tremendous wisdom in what author Uncle Bob shares. He sums it up nicely by saying:

If you are tempted to return null from a method, consider throwing an exception or returning a special case object instead.

* Note: A special case object would be one that looks and acts like the typically returned object. For example, Rails ActiveRecord #all method typically returns an enumerated list of model instances. When no records exist, it returns an empty array instead of nil. That plays nicely with a .each loop, saving us from trapping for nil.

PPL: Day 10 – Objects & Data Structures Part 2

This is part of the Peer Pressure Learning 30 series. You can read all about it.

Yesterday’s late morning led to a last-minute blog post. Thankfully, I read the text earlier in the day as it really warranted some consideration. Thankfully today, I’m back to the early groove.

Today’s reading: pg 99 – pg 102

The chapter’s concepts begin to take shape with the balance of the chapter read. While it’s really tough to see how it fits in with the rather opinionated Rails framework. I’d be rather interested in talking through concepts in this chapter as they relate to MVC.

The crux of the matter is the distinction between data structures (dumb classes that hold data) and objects (super-smart classes that operate on data structures). I quoted from the text yesterday, but really should have used this rewording of the Law of Demeter (a “well known heuristic”):

a module should not know about the inards of the objects in manipulates

That talks about objects, not data structures. The idea is that objects know very little about other objects in the system. They are allowed to chain through and know a ton about data structures, even if they’re chained several layers deep.

Ruby on Rails

So, what about Ruby on Rails? Clearly, the whole discussion is moot when you’re looking at a site/system with less than 5,000 lines of real code. It’s probably not large enough to worry about splitting into separate objects and data structures. Rails’ models hide enough functionality that a model can stay reasonably sized and satisfy the needs of a hybrid object / data structure. It’s a concern of balance, really. While a purist may demand that the smallest app utilize all the associated patterns and follow OOP to the T, I’m not in that camp. I’ve done enough consulting to realize that you have to balance cost (time) with the benefits (rather low in small projects).

A larger app begins to make the whole discussion rather interesting. I seriously have no answers on this side of the topic. If I’m taking the text properly, one would begin to make the models increasingly small, leaving validations and associations behind (and probably some of the callbacks). You’d then move more and more logic into library objects.

How the heck would that work? Hmm…I’m not really sure. I’ve done some work on having the model call a factory that instantiates the associated libraries, but I could also see some of that logic going into the controller. Putting it into the controller seems to be a great opportunity to duplicate code (not good). I think I like the idea of the model starting the process.

I’d love to hear from anyone with experience on really large, complex Rails projects. Talking through the concepts with someone experienced with 20-50k lines.