implementing mvc - using observer pattern - beginner to OOP

A

Adam Akhtar

Hi I started making a simple command line todo list application as a way
to get better at OOP. I decided to use a flat file db gem called
kirbybase.

Anyway the more I started programming it, the more it started to
resemble spaghetti code with ui getting mixed in with logic so I started
using google to find some patterns that might help.

One that came up was MVC which ive heard about from my very very limited
rails experience.

I tried implementing it (more like fudging it) but I dont think im giong
abotu it the right way. Ive looked on google for ruby specific stuff but
keep getting rails results that only provide an overview of it.

Can anyone provide any light on how to go about implementing it.

Will Kirby Base essentially be my model? Or will the model interact with
kirbybase?

If i use the observer pattern I guess the model should be the observable
with the views being registerd observers. Right?

What about the controller? What is it obesvign and who is observing it?

All menues etc will live in the views i think with user choices e..g
"add task" being registered in the controller along with the program
logic... is that right?

Regards to their interaction, do all talk to each other or is there a
chain of command. I.e. the models seem to speak to the views by updating
them, the controllers seem to talk to about the views and models? is
that right?

Finally does the singleton pattern come into play here? If i wrap the
database into a class should only one instance be made?

Apologies for my inexperience ;-)

I know this may sound like overkill for a simply todo command line app
but i think it will make great practice and setme up for rails in the
future.

any help will be of great assistance
 
J

Jean-François Trân

2008/11/8 Adam Akhtar :
Hi I started making a simple command line todo list application as a way
to get better at OOP. I decided to use a flat file db gem called
kirbybase.

Anyway the more I started programming it, the more it started to
resemble spaghetti code with ui getting mixed in with logic so I started
using google to find some patterns that might help.

One that came up was MVC which ive heard about from my very very limited
rails experience.

You should try SimpleConsole,

http://simpleconsole.rubyforge.org

sudo gem install simpleconsole

-- Jean-Fran=E7ois.

--=20
http://twitter.com/underflow_
 
B

Bob Hutchison

Hi,

Hi I started making a simple command line todo list application as a =20=
way
to get better at OOP. I decided to use a flat file db gem called
kirbybase.

Anyway the more I started programming it, the more it started to
resemble spaghetti code with ui getting mixed in with logic so I =20
started
using google to find some patterns that might help.

One that came up was MVC which ive heard about from my very very =20
limited
rails experience.

This is pretty much what MVC tries to deal with. There are variations =20=

on MVC as well.
I tried implementing it (more like fudging it) but I dont think im =20
giong
abotu it the right way. Ive looked on google for ruby specific stuff =20=
but
keep getting rails results that only provide an overview of it.

Can anyone provide any light on how to go about implementing it.

You would have had better luck looking into the smalltalk world for =20
MVC than the ruby world.

These two papers are pretty good I think. The second paper talks about =20=

two kinds of model: application and domain -- this is important.

<http://www.create.ucsb.edu/~stp/PostScript/mvc.pdf>
<http://www.jdl.co.uk/briefings/MVC.pdf>

Then read about value objects/models here: =
<http://c2.com/ppr/vmodels.html=20
Value models seem like a bit of a pain, but worth knowing about. =20
You won't likely need them at the start, and MVC + value models can be =20=

a bit complicated, but when your application starts getting complex =20
they can help.

As Jean-Fran=C3=A7ois pointed out, you don't have to do this yourself. =
On =20
the other hand, if you are looking to learn OOP this is a pretty good =20=

way, it might be a hard way, but you'll certainly have a handle on OOP =20=

by the time you're done :)
Will Kirby Base essentially be my model? Or will the model interact =20=
with
kirbybase?

MVC is an *object oriented* thing. So your model will interact with =20
kirbybase.

The rest of your questions are better answered by the papers I linked =20=

to.

Cheers,
Bob
 
A

Adam Akhtar

Hi thanks for the replies. I looked into MVC and i think its proably
overkill for what im doing and probably stretching my abilities too far
at this stage though does look like a good pattern. One think I dont
understand is what the controller would actually do in my case where im
just using the command line. I feel like i only need a model and then a
view/controller wrapped into one.

Well ive decided to just scrap mvc and just get the thing working. I
created two classes. One is a database class which wraps up kirbybase (a
flat file db plugin for ruby) and the second is basically the U.I i.e.
menu logic, getting input and presenting menus and stuff.

Im just not sure how to code their communication to each other.

class DB
..
..

def insert (task)
...
#some kirybbase calls here.
..
end

end


class UI

blahblahblah

def menu
puts "|A| to add a task"
...
...
end

def navigation
menu
input = gets.chomp
case input
when "A"
add task
etc
etc
etc
end




def add_task
new_task = new_task_form
add_task_to_db(new_task)
end

def add_task_to_db(new_task)
**what goes here?
end

def new_task_form
puts "Enter title for task"
new_task = Task.new
new_task.title = gets.chomp
return new_task
end

in add_task_to_db Im wondering the best way to pass the new_task
completed in the UI object over to my db object. Is there someway to let
the db class see the value of new_task? Should i be using an observer
pattern here? Should they be observing one another (if possible?)?

Im probably overlooking somthing dead simple here but im way confused.

any help most appreciated.
 
H

Hugh Sasse

Hi thanks for the replies. I looked into MVC and i think its proably
overkill for what im doing and probably stretching my abilities too far

It only needs to be a really simple controller.
at this stage though does look like a good pattern. One think I dont
understand is what the controller would actually do in my case where im
just using the command line. I feel like i only need a model and then a

It would take requests from the UI and only access the database when it
needs to. It will handle the business logic of what gets added and
removed. The UI would concentrate on how stuff looks to the user.
The idea, as you said that you want to get the hang of OO, is that each
class has a well-defined role. If two classes are in each other's pockets
then that is not good, because a change in one means a change in the other.
If two becomes 8, then this gets truly horrible.

The code that handles the money in your bank shouldn't care what cheques
look like when they are printed. But you want some logic in there that
handles what goes to a cheque when it's printed. If the bank decides
that cheques should have a blue background this year, rather than yellow,
then you don't want to change the code that sends the amounts to the
cheque printer.
view/controller wrapped into one.

Well ive decided to just scrap mvc and just get the thing working. I
created two classes. One is a database class which wraps up kirbybase (a
flat file db plugin for ruby) and the second is basically the U.I i.e.
menu logic, getting input and presenting menus and stuff.

Im just not sure how to code their communication to each other.

That communication is the role of the controller.
class DB
..
..

def insert (task)
...
#some kirybbase calls here.
..
end

end


class UI

blahblahblah

def menu
puts "|A| to add a task"
...
...
end

This bit below goes in your controller. It's a DB, so you will want to handle
Create, Read, Update, Delete for the tasks. That's probably enough to start
with, and Read and Update mean you'll need to search for tasks, so that
means you'll need to Tell the UI to display them.
def navigation
menu
input = gets.chomp
case input
when "A"
add task
etc
etc
etc
end




def add_task
new_task = UI.new_task_form
DB. add_task(new_task)
end

def add_task_to_db(new_task)
**what goes here?
# Nothing, it's already in the DB code. Isn't it?
end
This bit belongs in the UI
def new_task_form
puts "Enter title for task"
# don't put this here: new_task = Task.new
# new_task.title = gets.chomp
# return new_task

# You just want the UI to return a bunch of fields. the controller
# can validate them, and tell the UI: UI.bzzzt("Try again!").
end

in add_task_to_db Im wondering the best way to pass the new_task
completed in the UI object over to my db object. Is there someway to let

You don't, you just pass the possibly dodgy data back from the UI to
the controller. The controller checks before it stuffs a load of spam
into the DB.
the db class see the value of new_task? Should i be using an observer
pattern here? Should they be observing one another (if possible?)?

I don't think you need obsverver if the controller controls what is happening.
It will sequence which bits of UI show up. It might get errors from the
DB when you ask about all those tasks you didn't get round to adding. Then
it will have to tell the UI to display error messages, rather than task
lists.
Im probably overlooking somthing dead simple here but im way confused.

any help most appreciated.

HTH
Hugh
 
A

Adam Akhtar

Thank you so much for your help clearing that up. Im much closer to
understanding how things fit together. Id just like to confirm
somethings (please dont think im asking you to the write the code for
me, im not, i just like to be a bit more certain before writing out
lines of code ;-) )
This bit below goes in your controller. It's a DB, so you will want to
handle
Create, Read, Update, Delete for the tasks. That's probably enough to
start
with, and Read and Update mean you'll need to search for tasks, so that
means you'll need to Tell the UI to display them.


Ok so I have three classes now.
DB which encapsulates the DB and all the tables (at the moment there is
only one for tasks, in the future Id have anohter for categories,
projects etc)

Task_Controller which handles the menu navigation logic and any logic
such as what to do with a task when a user marks it as complete etc. It
will have DB related tasks such as Create, Read, Update, Delete.

Task_UI which will have basically all the output to the screen such as
menu text, prompts etc.

From this
new_task = UI.new_task_form
DB. add_task(new_task)

Question 1
it seems your implying my class Task_Controller should define an
instance of the DB and the UI within it, is that correct?

Question 2
Presuming Im correct about that, what is the relationship of the db to
the view? When the DB is updated is it the DBs job to inform the view
for it to update or does it inform the controller or .... C. do nothing
at all and just let the controller tell the view to update when it
thinks its best.

This bit belongs in the UI
# don't put this here: new_task = Task.new
# You just want the UI to return a bunch of fields. the controller
# can validate them, and tell the UI: UI.bzzzt("Try again!").

ok so i shouldnt create an instance of task in the UI. Rahter just
return a bunch of fields (a hash \ array? )which contain the input from
the user and let the controller figure out what each field represents
and whether its valid input. The controller will create a Task instance
and then pass it to the DB.

Question 3
When the UI presents say a form for a task to the user to fill is it
good practice to have things like

userinput = gets.chomp

in the UI or should that be handled by the controller. Im wondering to
what degree logic and presentation are seperated.
 
B

Brian Candler

Adam said:
class DB
..
..

def insert (task)
...
#some kirybbase calls here.
..
end

end

In a typical MVC, the model would be a class which represents the task,
rather than a class which represents the database connection (the latter
would be hidden away behind it). Hence something like:

t = Task.new
t.name = "Paint shed"
t.save!

...

t = Task.find_by_name("Paint shed")
t.completed_at = Time.now
t.save!

If you only have a DB class, then the controller can talk to it
directly, but you've lost the "M" from MVC.

This may be no loss - simple models are often dumb and just map directly
to SQL rows. But sometimes it's useful to put logic in the model layer,
e.g.

def full_name
"#{first_name} #{last_name}"
end

def full_name=(name)
f, l = name.split(" ", 2)
self.first_name = f
self.last_name = l
end

Here we have a virtual accessor that makes it look like the model has a
full_name column, even though the database actually has two separate
columns, first_name and last_name.
class UI

blahblahblah

def menu
puts "|A| to add a task"
...
...
end

def navigation
menu
input = gets.chomp
case input
when "A"
add task
etc
etc
etc
end

If you merge the view into the controller then you might get:

class TasksController
def list
tasks = Task.find:)all)
puts "You have #{tasks.size} tasks"
tasks.each { |t| puts t.name }
end

def show(n)
task = Task.find(n)
puts "Showing task #{n}"
puts t.name
end

def create
print "Enter task name:"
name = gets.chomp
print "Enter completion date:"
date = gets.chomp

t = Task.new
t.name = name
t.date = date
t.save!
show(t.id)
end
end

But what's missing is the sequencing: after showing task n there may be
associated actions (e.g. edit task n, delete task n, return to listing)

Maybe a good way to approach this is to start as a simple Rails app with
a sqlite3 backend. Then you can consider how best to build the UI part
which will (a) show the current view, and (b) prompt for next action.
 
A

Adam Akhtar

Thank you Brian and Hugh for your help. Ive got a much clearer picture
of where i should be heading with this now. I have a good enough
foundation to actually start coding something and then when mistakes and
spaghetti come flying my way I can look at things a little more in
detail and refactor.

Thank you once again. You have been a great help!.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top