Rails and real OO Java Petstore .. my turn now

So after great #wroclove.rb conference I’ve finally decided to roll my own design and implementation of Java Pet Store app.

It’s a well specified app with known functional requirements. It’s quite real world scenario app. Its implementation can be compared to other platforms. So it’s a good showcase for what I’m going to present.

Will Include (not limited to)..

  • aop
  • domain usecases
  • facade
  • roles
  • coffeescript mixins
  • rails
  • rails ActiveRecord .. not
  • … ? who knows..

Empty github repo waiting..

Share on Twitter

View is thin, dumb and a servant of domain model.. not the other way

I’ve came across this twice lately…

Two independent developers were trying to explain to me why their model is not readable (and maintenable) and doesn’t reflect real domain. Objects were wrongly associated together, and real world classes – were missing and not defined!

The wrong explanation of a dev was:

..because, a user using “admin UI” selects a card text and assigns bunch of NUMBERS (cell ids) it appears on .. No need for “board cell class”

Who cares how an user is using an app.. It should not have any, or minimal impact on how business domain is modelled, even db is designed..
Should it be a browser, a console app, fully dynamic Ajax website or an iPad app.. It’s only how the app looks, and how presents its information about data.

Views change, user preference change. View is a thin layer, only a presenter. Should not drive the design of domain layer.

An app was…

…I was looking at how some game was designed, a board game, and it was missing representation of a BoardCell

In this small OO world:

  • a game has a board
  • a board contains many board cells (hexes)
  • a board cell contains many cards, of which some give special powers

So I was expecting at least this below: (you can copy&run example)..
…But what I found something different

There was NO BOARD CELL REPRESENTED AS A CLASS.

I need real world model, close to business, close to the domain. I want ALL THE REAL CLASSES BE THERE. So I can touch them and work on them.

So, try to cut any class from above code. It will make no sense, as all the objects make sense there. It’s the pure model.

Now, based on this code you CAN start building views. Views may or may not present all the data. May only show final bonus of a player, of a whole board.. who cares.. that is what is view for.. to present, not to define!

Try to imagine your view changes, what then.. would you really want to have model not being a mirror of a real world, and change both: the view, the model … thought so :-) So don’t

 

 

Share on Twitter

My Law #2: Business Logic .. and forming Use Cases

As far as I remember I was always very eager on trying to transform natural world – it’s behaviour and information – into a computer. I always wanted to achieve two things:

  • tell the computer how real world is modelled
  • tell it in a way that a human can read and understand it

So the effect is

Implementing Business Logic of a domain is the most important and funny part to do

It has many impacts

  • what is the model?
  • what are the classes and how they look?
  • how to persist data to a storage?
  • how to deliver data to an app user and how to interact with the code
  • where business logic should be implemented
So I always wanted to be closer to the model part more than to other. It looked easy at first to create a Player class, it’s behaviour and data. And I was implementing high level business operations into the model, not the controllers layer nor the view.
class Player
  constructor: (@name, @age) ->

  throw_a_dice: () =>
    ...

  pick_a_card: () =>
    ...
.. but something was missing.. I discovered it just lately thanks to friends and possibly by waking up from a long 4-year hibernation that I was missing a representation of use cases in the system. TA daAA!

It is very important to split your models into at least 2 parts, maybe even 3.

  • “use cases”: a part where high level use cases, scenarios, algorithms, business logic is implemented (SelectingFirstPlayer, RollingADice, MakingAMove, PlayingMonopolyGame, ..)
  • “base models”: a part where base classes are implemented with their basic methods attributes that can be reused in use cases (Game, Board, Player, Pawn, Dice, Move, ..)
  • “storage”: a storage part (maybe, if it’s configuration would be too tight into base model classes, that it needs a separation)
It’s so obvious a use case must have a shape in the system somehow

I’m not yet sure what should be the scope of a use case. Using an example of a popular Monopoly board game, should a use case be “playing monopoly board game”, or only “throwing a dice and making a move”..

But I’m pretty sure all use cases must have a form in the system by being at least a class, that has this single responsibility: telling the whole algorithm of a use case in one place.

 

Share on Twitter

My Law #1: DRY .. or not

I think that’s the rule that drives my programming style the most is:

#1: Keep it DRY: Don’t Repeat Yourself

more here http://media.pragprog.com/articles/may_04_oo1.pdf from smarter than me

But there are 2 very different parts of the code where DRY might and might not be applied: programmer’s code and “high level” domain logic

A) Programmer’s code

I say, it’s a place quite deep in your code, rather related to implementation and less to design. Those are rather controllers and views, and deep parts of model implementation, every helper and utility class. Details far away from actual functional requirements, use cases, business logic.

So there – in programmer’s world – I spend lots of time thinking how not to write the same/similar code twice. Really, I can even spend 10 hours or few days of thinking and writing ZERO code..
.. because I’d rather shoot myself in a foot with a railgun than used dumb-COPY-&-PASTE. We nowadays know it’s PLAIN WRONG, do we..

  • copy & paste exact parts of code is lazy (“lazy” the wrong way as opposite to being positively lazy as in yagni)
  • copy & paste similar parts of code might look and is quick solution at first, but it’s not. Someone WILL try to understand and refactor it later and WTF you
  • it’s about respect to other developers
  • it’s about write-once, read-100-times. It’s been always this way. So why bothering people after you with your unsolved problems
  • copy & paste is a smell for immediate action: extract similar code into a method, pass parameters, whatever.. make duplication gone
  • and obviously if a change must be later done to all duplicates, it must be made in X places instead of ONE

So this is BAD code. Effect of dumb COPY&PASTE&CHANGE-ONE-VAR

B) Domain Code

.. we must make distinction on the “A)” code made for programmers and “B)” code meant to describe our natural world, our domain specific requirements.
This is a “high-level” domain code, possibly close to what customer say and do; to what their use cases describe. So it should really tell what it does.

Such code should not distract reader by forcing the reader to jump & dive around in & out of methods to see how things are implemented. I’d have all code served in front of me instead

In my opinion in domain code it is more important to see the intent of the code than to be pure DRY. I must admit I don’t make some strict rule on that yet. It’s rather my intuition today.

Applying all the fancy programming patters and refactorings just to make code few lines shorter does opposite and makes intent, the flow, the algorithm not clearly visible.

I say there are 2 cases where I’m not always fully DRY

  • acceptance tests – simulating user interacting directly with application (via browser mouse clicks, keyboard, triggering events, etc)
  • use cases – the most important domain code, domain algorigthms, business logic

So I would live with such code..

.. and I think I would also live with this one, but maybe bit less comfortable in the long term..
..although at first those 3 cases now look shorter and more readable, but they also PRETEND that they do something by a nice method naming. In fact those methods might do sth completely different. They hide details, but those details ARE IMPORTANT, so should not be hidden

PS. .. methods longer than 10-20 lines might be OK for domain code, but they’re rather on the longer side

Share on Twitter