Wednesday, November 10, 2010

Of Horses and Carts

As developers, we like to code.  We want to write code.  It's what we do.  So, naturally, when a project begins what we want to do is dive in and start writing code.  From a proper planning perspective, this is generally frowned upon.  And for good reason.  When you're just starting to plan and haven't flushed out the details and don't have a firm grasp on the actual requirements (not just the documented requirements that some business user wrote down) is precisely when you shouldn't be etching into stone the logic to be used in the software.

But this reality can easily be (and often is) misconstrued as a mandate to not write any code just yet.  This is a fallacy.  Writing code isn't the problem.  Writing code that's etched in stone is the problem.  And overlooking the actual problem by mandating against what is essentially a means to the problem very easily leads to not solving the problem, but instead just moving it somewhere else.  Somewhere sinister.  The data model.

We've been writing software for years, and we generally know how it goes.  Almost every developer still does this just out of habit.  First you build your database and model out your tables, then you write your code to sit on top of that.  Right?  That's how everyone has always done it, so it must be the way.

Sadly, and at the cost of untold man-hours, it is not the way.  But it's just such common practice that people continue to behave in this manner out of nothing more than habit.  It's what they know, it's how they think, and it's a tried and true approach that management understands so it's the safe route.  (Safe for the developer, not for the ongoing maintenance of the software.)

What is essentially happening here is that the early attempt at solidifying the requirements is being etched in stone in the database instead of in the code.  And raise your hand if you think that re-factoring a database later in the life cycle of the software is significantly more difficult than re-factoring the code.  That's what I thought.

It all comes back to my favorite of favorites... separation of concerns.  You may be using proper IoC, you may be putting in hard assembly or even service boundaries between your layers.  But you haven't flushed out all of those dependencies.  The overall structure, in every direction, still depends on its core.  And when you first begin designing the software you are essentially designing its core.  The choice is yours... Should the core be the data model or should the core be the domain model?

Let's go with the common approach, the data model.  You build your ER diagram, create your tables, map your keys, create your association tables for those pesky many-to-many relationships, etc.  You now have a core database upon which your software will sit.  Essentially, you now have this (pardon my crude diagrams):
Your layers are separated, and that's all well and good.  But notice a subtle dependency there.  The overall shape of your software is governed by its core.  There's no getting around this, not unless you do what will likely amount to more abstraction than you need in a highly de-coupled service architecture.  (Get ready for tons of DTOs and "class explosion" for that.)  Even if these are broken apart by assembly and dependency-injected and all that happy fun stuff, there's still the underlying fact that your software's core is its data model.  What happens if that data model ever needs to change, or if you need to move to a different data store entirely?  A lot of work happens, that's what.

Consider instead shifting your core a little bit.  Imagine for a moment breaking that cardinal rule that "thou shalt not code first" and actually begin the design by creating your domain models.  In code.  What about the database?  You can figure that out later.  Or, at least in my case, hopefully a trained data modeler can help you figure it out later.  (Developers like to think we're also data modelers, but most of us just aren't.  A lot of that comes from the fundamental differences in design and function between object-oriented thinking in code and relational thinking in an RDBMS.)  Now, you have this:
The structural dependency is still there, but the core has shifted.  Your data model was built to accommodate your domain model, instead of the other way around.  By this approach, the data persistence is simply an interface which interacts with the domain, no different than the UI or anything else that hooks into the central domain.  The idea here is to be able to re-factor things more easily, especially in the data model (where significant growth can lead to unforeseen performance problems and scaling issues not evident in the original design), without impacting the entire system.

Many times this boils down to a cultural problem, really.  Businesses have spent decades with the understanding that "the data is paramount."  While there is generally truth to this statement, it should not be extended to believe that everything about the database is the core of your system and all that matters.  After all, the engine which drives that data plays a fairly critical role in your business.  Unless you're dealing with simple forms-over-data applications and simple rails-style interfaces, you would probably do well to consider the importance of all that business logic.

A common analogy in the English language is "putting the cart before the horse."  And you know how developers love analogies...  The cart is your data.  It's the payload that's being transported.  The horse is your engine.  It drives the data to and fro.  In the age-old struggle between cart-makers and horse-breeders there is a debate over which is the more important part of the system.  Without the horse, the cart doesn't move.  Without the cart, the horse has nothing to do.  Both are valid points to be sure, but when designing the system which natural construct ends up being the core?  No matter how well you abstract your horse-to-cart interface, there's still a natural architectural dependency in the system.  And it's a hell of a lot easier to build a cart that fits your horse than to breed a horse that fits your cart.

Thursday, November 4, 2010

Don't Forget To Track Your Hours

I was entering my hours worked into my employer's time tracking system today and it got me thinking about that whole process from a developer's perspective.  Now, it generally goes without saying that we as a breed don't like doing that.  We're here to work with code, not tell you how long we spent working with code.  But it occurred to me as I was entering my time that I didn't entirely mind doing it.  I didn't feel inconvenienced or annoyed at the prospect, and most of all didn't need to be reminded to do it.

We're intelligent people, we know why management wants and needs this information and how valuable it is to the company's bottom line.  But that knowledge alone isn't enough to capture this information and successfully report on it.  The process itself must be scrutinized and tailored to the actual daily needs of the employees.  Otherwise, you're going to spend extra effort trying to get your employees to enter their time, they're going to spend extra effort listening to you and finally entering it, and the numbers just aren't going to be good.

Let's take a look at some of the time tracking methods I've used over the years...

Many moons ago I worked for a small company in a small town that primarily set up computers and small networks for small businesses.  As the company grew, myself and eventually another developer were added to expand into small websites and custom applications.  This company had a home-grown (developed by the only other guy there who knew a little VB before I came on board, I think) time tracking system.  Basically, it was a little application with a list of "open projects" and functionality to clock in and clock out.

I never used it.  Well, I used it a couple times at first, but that quickly faded into not using it at all.  It was silly.  I (and the other developer when he joined the team) could not be bothered with tracking project time.  The application reported to a spreadsheet and, upon the manager's request for specific project times, I would just manually send a single project's time to the manager.  It was a rough guess.  How do I know how long I spent on that project?  I was doing 10 different things that day.

The system worked well for the network guys, because more often than not "clocking in" to a project was done before they actually went to the client site, and "clocking out" was done when they returned to the office.  Made sense.  But as for the developers, we saw it as pointless.  (As the company grew we also brought on board a PC tech guy and gave him a workroom to perform various machine maintenance.  I don't think he was even asked to use the system.  If he was, he promptly ignored the request.  I mean, when he has 5 open computers on his bench, 2 are formatting, 1 is installing something, one is booting up, and one he's actively using... what "project" is that under?  Is he expected to "clock out" and "clock in" each time he wheels his chair from one machine to another?  Didn't think so.)

Fast forward through some various other endeavors in my career to a more recent example.  Two jobs ago we used a system called Rally.  And, although this sentiment wasn't universally shared by every last one of my co-workers, I actually really liked it.  Sprint planning and task break down was a pain, and I'm fairly convinced there's no way to ease that.  But actual time tracking was quick, efficient, not inconvenient in the slightest, and actually a joy to do.

Logging work hours was really streamlined in this system.  I look at a grid of my tasks for the current spring, I mass-edit a few numbers of how many hours I spent per task that day, and I save.  Takes maybe 30 seconds of my time.  The UI was clean and intuitive.  And burndown charts are just pretty to look at, naturally providing incentive to take those 30 seconds.  Now, I'm sure the system could be horribly abused, and may have been for the co-workers who didn't enjoy it as much as I did.  (It didn't account much for distractions, so "putting in time" during a day where one's time was wasted by a dozen other people just isn't going to sit well.)  But, all in all, the numbers were good, up to date, and once we got used to the system we didn't need constant reminding and fighting from management to enter our time.

Step forward into another job, where we used a system called Remedy.  It was awful to say the least.  The system itself is highly configurable, so perhaps it can be made to be better.  And I'm certain we were on an old version, so maybe it's improved since then.  But, where the rubber hit the road, it was an absolute pain in the ass to use.  Entering information into the system or retrieving it from the system was akin to a scavenger hunt through Hell.  Needless to say, I patently refused to use it.  Early on in my time at that job there are a few entries that I was persuaded to put into the system, but for most of my stay there the reports had me flat-lining across the board.

There was absolutely no incentive to enter my hours.  The system was bulky and awkward and served no purpose to my daily work other than to explicitly get in my way and prevent actual work.  It may have been perceived that I felt that I was above such pettiness and wouldn't belittle myself to track my hours.  Giving some thought on the subject, I'd be lying if I denied such a sentiment.  It wasn't in any arrogant way, really.  It's just that, as a professional, it was a waste of my time and effort.

Most of the employees there had been there for quite some time.  Many had come up through other groups and other departments and perhaps this was all they'd known for a long time, for a good number of them perhaps even all they'd ever known.  They'd gotten used to it, I suppose.  It had beaten them.  "That's the way we do things here" was a common utterance.  (On a side note, I never understood how maintaining the status quo so staunchly made any sense in a company plunging into bankruptcy, but I digress.)  The bottom line was that I wasn't going to use it.  My time is valuable enough that I'm going to spend it doing the work I was hired to do.  If you don't think my work is valuable, then fire me.  (Heh, funny story about that, but I again digress.)

Step forward again to my current job.  Here we use a system called Jira.  I'm pretty happy about this, actually, because I'd wanted to use Jira for some time now and learn more about it.  Perhaps we may even begin using some of its companion products, which would be sweet.  Anyway, entering time is once again a clean, quick and simple process.  It's not quite as streamlined as Rally, so that one is still my favorite to date.  But it is quick and simple and the UI provides enough direct incentive to make it happen on a nearly daily basis.

Logging work still prompts for work descriptions and various other nonsense that I continue to leave blank.  Honestly, the description is in the task.  What did I do for those 3 hours?  I did what was already described.  Hopefully they won't grill us for more information and more tracking.  I honestly doubt they will, it's a pretty casual and extremely efficient place here.  If something holds up progress in any way, it's not going to last.  There is no "status quo" here other than getting the job done.

So, looking back, it would seem evident that it's not really in a developer's nature to avoid time tracking entirely.  It's not beneath us or a waste of our time, provided that it's done properly.  The time tracking system should be tailored to the work, not the other way around.  (And a fantastic example of that is the first example above, at least for the client-site network guys.)  If you're trying to fit the square peg of work into the round hole of the time tracking system your purchased, don't expect good numbers.  But if you, as a manager, take some time and actually understand how your employees think and work and act then you can get that useful business information from them without an ongoing battle simply by adjusting the system to accommodate the work.

Wednesday, October 20, 2010

Developer must reads

I had mentioned this a couple of times to people about how a book would fit into my must reads or where it would fit in. I figured I would try to dump that list here while trying to list them in a suggested order.


  • Code Complete: 
    • gets you thinking about how you structure and write code on the line or function level.
    • talks about developing good coding habits (comments, naming) and skills (debugging)
  • Pragmatic Programmer:
    • starts talking about basic principles such as DRY, goes a step further then Code Complete
    • talks about learning your tools and introducing some ideas of craftmanship
  • Apprenticeship Patterns:
    • establishes some ideas of how you can attack your pursuit of mastering your craft
    • some ideas of how to stay organized and on track as well
  • Refactoring:
    • how to make your code better when you start to see the pitfalls of your approach
    • can make it easier to know how to tackle or see/smell the possible problems and code smells
  • Mythical Man Month:
    • start introducing you to some on going issues with managing software teams and projects
    • contains some timeless papers that introduce Brook's Law and No Silver Bullet
  • Design Patterns:
    • now getting up to lower system interactions and design
    • starts to develop some common design terminology
    • help you understand categories of problems and possible solutions
  • Applying Domain Driven Design:
    • takes design and development approach a step further
    • ties in some design patterns, test driven development, and refactoring together
    • starts to introduce you to architecture patterns
    • you get to see the workflow and thought process of how a system comes together
  • Patterns of Enterprise Application Architecture:
    • now we get to how to establish components and layers of a system
    • getting to applying the same ideas of Design Patterns but to a higher level of design

Now I need to finish a couple of those books and figure out new books to read (probably something on XP or Agile, TDD, continuous delivery, and DSLs), but that is a series of books that should probably be stretched out over the beginnings of your career (say first 2 or 3 years) because some of them will require a mentor or experience to start to grok (I'm still trying). 

It's probably debatable about where some of them appear (maybe Applying DDD before Design Patterns?), but these are all books that help regardless of technology. You'll probably enjoy having them on your self after your done as well (for reference or the reminder). 

Besides these books you should strive to master your primary programming language and dig into core technologies you use. After that you should also try to explore other languages and technologies even if they don't apply directly to your work.

I'm still trying to accomplish some of those last points but I imagine I'll always be going after something.

Tuesday, October 12, 2010

To learn is to abuse

I know sort of a strange title but I feel like there is some order of operations I'm following in my growth as a developer.

Learn thing -> abuse use of thing -> actually start to understand thing (hopefully) -> use thing appropriately -> learn new thing -> ...


My thoughts are interfaces are starting to change...mature? I think the .NET convention of an 'I' (ex: IEncryptionAlgorithm) prefixed defeats part of the point. I think that encourages us to see it as an interface code construct and not the required object description that your module/class/method wants. Perhaps Java's '*able' (ex: Runnable) is a better one. I hope that makes sense but I'm starting to think a lot of developers have focused on "this is a class" or "this is an interface" when both are actually an object description and when you take that in as a parameter you are saying I require these members. When I start thinking that way I start thinking that class methods should be virtual by default and that in general we probably don't use interfaces correctly (hell a lot of people don't use them at all I'm sure). Just having a class by default have virtual methods means we could mock a class the same as an interface. This does mean that you couldn't rely on a class's implementation at runtime but you shouldn't be programming against the implementation anyway.

Of course then I think about how it's easier to reason about a class if it's sealed up nicely. It's also easier to reason about code interactions if types are explicit, but then again it's easier to write tightly coupled code if types are explicit. Perhaps since class members are by default non-virtual, proper use of things like TypeMock should be encouraged. 

My biggest objection is if it allows you to open up the class and mock out a hidden internal dependency. If you needed to mock an internal dependency to properly test a class then perhaps it should be an explicit dependency instead (pass in through a parameter). 

Beyond mocking, interfaces should be encouraged as well since they are what provide real modular and reusable code. Type hierarchies only project shared/related implementation reuse which I don't think helps an application on a whole, just a piece of a subsystem or layer. They are best at describing related types, perhaps that's all they should be used for and not for passing around or interacting between subsystems.

I think this has been influenced by my interest in dynamic and message passing style languages. I also think this is just my understanding of object-oriented design hopefully increasing (you never can judge your own aptitude). So I'm thinking I'm leaving behind a phase of my understanding where I probably overly used classes and probably about to enter one where I overly use interfaces. Of course this only really matters in static languages where you have to worry about types. Maybe I'm over thinking things...or maybe I should just go back to Ruby or Python.

Thursday, October 7, 2010

The Times, They Are A-Changin'

Ya, I've been pretty quiet lately.  Turns out I've been pretty busy lately.  See, I started this blog when I started a new job and a new phase in my career.  I just figured it was time to write some stuff and generally cultivate the idea of writing as an important part of my overall career.

Well, I've recently started at a new new job.  We don't need to get into all of the ugly details about how the old new job ended, suffice it to say that it was a career learning experience.  But we can all readily agree that I definitely wasn't happy there, and everybody knew it.  There was friction.  A lot of friction.  I wish them well and all, but it's just better for everybody that I'm not there.

So here I am at a new job.  This one is kind of an interesting mash-up of the industries of my last two jobs, but leaning more towards the former than the latter.  But the overall culture of this place is definitely a far cry from either of the previous two jobs at every level of the organization.

Anyway, being the new guy at a busy place, and trying to pick up various psychological pieces that have fallen over the past few years, you can imagine that I'm quite busy these days and that would explain the lack of recent posts.  (The 3 hours per day of driving doesn't help either, but that should change at some point.)  I was hoping originally that there would be more active contributors here by now, but it is what it is.

I can, however, take a moment to jot down some initial impressions of the new job.  A pros and cons list, if you will...

Pros:
  1. It pays more.  That's always a plus.
  2. Casual day every day.  Shorts and flip-flops are even acceptable.  (Though I despise flip-flops and would never be caught wearing such things, but shorts are a nice option on hot days.)  I'm enjoying sporting the t-shirts on my first week, but I imagine I'll mix it up with some polo shirts just so I'm not always wearing t-shirts.  Besides, why would I want to wear out my best t-shirts?
  3. Software best practices.  None of this "we're a Microsoft shop" nonsense, but rather a corporate culture from the top down to use what works for good long-term reasons.
  4. Good talent pool.  I especially hear great things about the lead architect here.  Basically, I enjoy working with peers from whom I can learn things and refine my craft.  This seems to be the kind of place where they focus on building a good team and let the team figure out how to handle the projects, rather than tightly defining individual roles and ending up with vaguely qualified people who don't actually work well together.
  5. Great corporate culture and environment.  The people who work here seem to genuinely enjoy working here.  I don't hear any complaining, I don't see anybody slacking off or taking breaks to vent, none of that.  Everybody's busily working away at things they enjoy doing.
  6. Venturing outside of my comfort zone.  One of my main reasons for leaving my previous previous job was because I was becoming too settled into my role.  I didn't want to build a career on being the guy who supports one legacy product.  Furthering that, I continue to not want to build a career based on one technology or one platform.  I love .NET, and I enjoy furthering my skills as a .NET developer, but at this job I'm currently doing a good bit of PHP (which we'll be converting over to .NET eventually, but for now changes to the existing PHP product need to be made).
  7. Working with a friend again.  I've really missed daily interactions with the friends I made at my previous previous job, and it's good to be working with one of them again.
  8. Change of scenery.  For one thing, I like working in a proper office park again (the variety of lunch choices alone is a welcome change).  But this is also 90+ miles from home.  It's in a whole new market.  If it works out, we can relocate here permanently (so far this is a 3-month contract gig with a possible hire, but if that doesn't happen I can just slip into another contract gig or something, no big deal).  But overall it's good to make contacts in another market.  If you spend your whole career in a single (especially small) market, you have to keep the bad contacts along with the good.  Old bridges are burning, and even if we didn't start all of the fires it's still best to avoid trying to cross them.
  9. Individual accountability.  As Tony puts it, "giving you enough rope to hang yourself."  Basically, initiative and project ownership are welcome here.  If you want to do something that will be good for the company, then do it.  Just make sure you do it.  With initiative comes responsibility.  They don't expect us to be perfect, so some room for mistakes is acceptable.  But overall I like the idea that it's not all surrounded with a vast sea of red tape, nor are we begging at heels of the on-high masters for a little bit of leeway to do our jobs.  We're allowed and expected to be leaders here.
  10. No offices.  Seriously, this is kind of cool.  The cubicles are very nice and very spacious, and everybody short of the CEO is in one.  The only office is for the CEO, because he clearly needs a place where he can close the door and be on the phone or hold a private conference without having to book a room or anything like that.  And even his office is all glass with full view of everything going on.  Even his monitor is facing outward so he's not hiding anything.  But everybody else is in a nice cubicle.  Some have better window proximity than others, but there's no avoiding that.  Generally, though, I find this brings a nice sense of flattened management structure to the whole game.  We're all peers, we're all members of the same team, we're all in this together.
Cons:
  1. Long commute.  90 minutes each way is pretty exhausting.  It's likely that I'll get a cheap apartment in the area, but that still feels like money down the drain.  It still comes out to a net increase, but doesn't feel right.  (Though the added sleep available in a local apartment would be more than welcome.)  Maybe I can work out some remote VPN time instead.  The lead architect suggested that, and I definitely like the idea.  But until I get fully entrenched in tasks and heads-down coding work, I need to maintain a presence in the office.
  2. The lead architect is hard to read.  He's clearly a nice guy, that much is obvious.  But it's hard to tell if he's being nice or if he's upset at something or if something else is wrong.  To be fair, the guy is probably tired as hell.  It's a demanding job.  And let's also be fair on my end of this interaction... I have below average body language and situational awareness and I'm paranoid as hell.  Not a good combination when dealing with subtle interpersonal interactions.  So that's more a con for me than for the job.
  3. The carpet texture is uneven.  Seriously, this bugs me on a daily basis.  It feels like the soles of my shoes are unevenly worn or that I have something in my shoe or something like that.
  4. There's no secret garden.  In the building there are two communal sets of men's/ladies' rooms, that's it.  This means that, on a not-so-fresh day, I don't have a private place to poop.  I'm thinking about the greater good of the community here.  You don't want to be around when this bomb goes off.  At my previous two jobs I had sought out, found, and retained designated safe zones for accomplishing this task.  Here there simply are none.  Sorry guys.
That's about it for now.  I'm sure I'll think of more stuff later, but I think this sums up the experience so far quite well.