Saturday 4 May 2013

OO - Design is better than Design Patterns.

The following article, which talks about object orientation, mainly focuses on design over design patterns. Which is the enemy? Generic over used, incorrect solutions or well thought out and well constructed objects?

I don't think many, if at all any person has actually done oop and not come across design patterns.

Design patterns are bad design. They don't solve any problem they claim to. If anything they do the opposite. I use this site as reference http://www.oodesign.com/

Everyone knows the singleton was possibly the worst design pattern, and claimed to be an "anti-pattern" I don't think this is true, I think all are anti-patterns.

Example: A factory design, which is one of the most used patterns breaks SOLID. The factory depends on whatever it makes, hence if the thing it makes changed then the factory becomes useless, if the thing is deprecated or deleted then the factory should be the first thing to go. Anything which uses the factory suddenly falls apart. Yet the factory, or something which creates objects is integral to most programs.

I do not claim this proves anything, but it fuels this blog.

I think the solution is to use oop and not rely on patterns. To learn how to solve problems and not how to use "generic" solutions. To spend time in designing and creating a lasting solution rather than save time using a hashed, over used and let's be honest, dull solutions.

How is this done. I think the name says it all really. Object Oriented. When one creates an object they should ask themselves, "Is this really an object?" e.g. UserBuilder... are you really an object?

Example: I have a User object. When someone wants to create a new user how do I do this? Typically one might use a builder or factory to create the user and then process this using something such as a command design or a strategy design, dependent on how complicated the system is. But what is wrong in letting the User do the work?

What is better user.create() and user.save() or userFactory.create() and userStratergy.save().

One might argue that the factory and strategy do far more complicated things and should be segregated  In this example I disagree.

If I change the user then my save and create method can changed at the same time. If I delete my user or replace my user than the create and save method both change at the same time. The user has to do more than one thing, but at the end of the day the user object and all information about the user are self contained.

I like this to think of this as objects doing their own dirty laundry. Beyond breaking the S in SOLID, I don't see anything wrong with it. Does it even break the S? The user can save itself and create itself... Is that a bad thing? If designed correctly then the User object serves more than 3 different objects all claiming to do different things, but all relying on the user even existing.

There is more to oop than solid, but this is something in which just about everybody remembers and something in which everyone uses to prove code is bad (I am guilty of this). In my opinion design which breaks techniques such as solid, but last longer and are easier to maintain and understand are better than patterns which fall apart, lead to arguments over names and what they do.

(Inspired by +martin odersky's +Coursera  course with the Nothing object and the Nil objects, unless I have missed something that is a brilliant way to remove null pointer exception from my code)

One other thing oop should solve is the ability to remove nulls and null pointer exceptions from code. The only reason we worry about something being null is because we fear we have not created a new object. But imagine if the default behavior used was a useful object. Whilst there was nothing there, it can still be acted upon.

Similar to the null object pattern but with less nulls. The moment I introduce the word null, either in test or in code (outside of the object name) I should create the null object instead.

In the example above let's create the NullUser. If one wants to do user.save() and user was null object you would get a NullPointerException in java or in Scala a message about not being able to act upon Nothing or Nil (which ever is appropriate) . What if instead user.save() threw a "can not save the null user"? or user.save() "creating a user first as this is the null user." The latter might be a little dangerous, but at least your system didn't have a crippling exception which gets replaced with if(user != null) user.save(). Also if the latter is designed well then it is superior to even throwing an exception.

Maybe I missed the memo which cleared this up. But if people used object orientation, with the thought in mind "do your own dirty laundry" then you wouldn't need to spend time arguing about whether we should use an assembler, builder or factory, all of whom introduce debt and aren't good ways of oop.

If design patterns are the way to code oo languages then designing something write should reveal these patterns within the code. They are worth knowing, but are they worth applying?