Ways to discover what design patterns to use - semantic approach possibility?

Hello all,

Here’s the project:
Create a system that holds thousands of abandoned animals from shelters in my country. This is big.

I have created the briefing (12 pages or so).
I have created the Database UML (big piece of paper btw).
I plan to use git (so I will need to configure it somehow, and learn how to use a subversion system).
I plan to embrace MVC pattern (I grasp the basics).
I plan to use Zend Framework (I grasp the basics).

However, now I have a hell of a head-hake in front of me.
I will probably need a way to understand how to pass from the UML database to the design patterns that I need to use, before the development starts and, I’m presuming that this needs to be the next step.

Is there a methodology for doing such a passage?
Or the discover of the required design patterns is done on another way?
Is there any semantic approach in order to figure those out?

Any comments would be more then welcome.

Thanks in advance,
Marcio

No, not really. Patterns tend to emerge as you refactor your code. Trying to work them in up front smells of premature optimisation. MVC is an exception since Zend Framework uses it.

Thank you all. Really. Some of the post were, unfortunately for me, quite advanced. But I will make my path upon the good advices I was able to read from here.

Thanks you all again,
Márcio

“It’s important to really understand your code and what its doing.”

Couldn’t agree more with Chroniclemaster1.

In practice, I think this is not as hard as you think it will be. If I’m understanding you, it sounds like you’ve got your DB design all laid out, and now you’re wondering what kind of application objects will go with it. You’re getting very generic advice, only because we have such a generic description of what the program does. If you’d like something more detailed, just give us a couple examples of the kinds of abstractions that you’re going to be working with. In general, however, here’s how I start attacking the problem.

I start off with a very high level function that runs my entire program. It calls various functions which handle the details of how that happens; these are still very high level functions with semantic names that tell you exactly what they do. These functions call lower level functions which call lower level functions, or whatever until you reach the point that the functions no longer need to call a lower level function to actually implement what you want done, they can just do it. The functions should do one - and only one thing, that’s how you keep them under control and can figure out where you should stop calling nested functions.

Also, if you are still learning design patterns, my favorite book on the subject is Eric and Elizabeth Freeman’s Head First Design Patterns. http://www.amazon.com/First-Design-Patterns-Elisabeth-Freeman/dp/0596007124/ref=wl_it_dp_o?ie=UTF8&coliid=I1OAMKDF6PUK5X&colid=1INX8C29WI78G
It’s an excellent mix of theory and application. It’s not something that will show you how to design your program, but it will show you patterns to look for. When you plan out your application design, as you look over it a few times, you can probably start to see a factory or two that would make things simpler and easier to do, a good use for an adapter, maybe even something a little more fancy. As you get more projects under your belt this will become more natural and you’ll see more. The important part is not to use a design pattern before you understand it. It’s important to really understand your code and what its doing.

Hi…

Yes and yes :).

You discover the patterns during development. While you should learn the patterns offline, I wouldn’t have them at the forefront of the design process. They are a toolbox. You wouldn’t start building a kitchen table by trying to decide which tools you would use. Rather, you are halfway through and you discover you need something. That’s why builder’s merchants are open on Sundays ;).

Here is the heuristic you are after:

  1. Take one thread of a use case.
  2. Implement it any old how.
  3. Take another thread.
  4. Implement it any old how.
  5. Look for commonality.
  6. Factor the code so that commonality is collected into functions. Aim for clarity of code. No globals, pass everything.
  7. Any block of code that is unclear, group into a function as well.
  8. Implement another thread any old how, but use your existing functions if they are instant drop-ins.
  9. Once working, factor again to remove duplication. By now you may find you are passing similar lumps of stuff around from function to function. To remove duplication, move these into objects.
  10. Implement another thread once your code is perfect.
  11. Refactor to avoid duplication until bored.

Now the OO bit…

  1. By now some candidate higher roles should be emerging. Group those functions into roles by class.
  2. Refactor again with the aim of clarity. No class bigger than a couple of pages of code, no method longer than 5 lines. No inheritance unless the variation is just a few lines of code.

From this point on you can cycle for a bit…

  1. Implement a thread of use case any old how.
  2. Refactor as above. Refactoring includes renaming objects and classes as their meanings evolve.
  3. Repeat until bored.

Now the patterns stuff!

Once you have a couple of dozen classes and quite a bit of functionality up and running, you may notice some classes have very similar code, but no obvious split (no, don’t use inheritance). At this point consult the patterns books for options on removing the duplication. Hint: you probably want “Strategy”.

The following repeats…

  1. Implement another thread of a use case any old how.
  2. Refactor methods down to five lines or less, classes down to 2 pages or less (preferably a lot less), look for patterns to remove higher level duplication if it really makes the code cleaner.
  3. Repeat until your top level constructors either have lot’s of parameters, or you find yourself using “new” a lot to create objects inside other objects (this is bad).

Now we need to clean up the dependencies. Any class that does work should not use “new” to create things inside itself. Pass those sub objects from out side. Classes which do no mechanical work are allowed to use the “new” operator. They just assemble stuff - we’ll call them factories. A factory is a role in itself. A class should have just one role, thus factories should be separate classes.

  1. Factor out the factories.

Now we repeat again…

  1. Implement another thread of a use case any old how.
  2. Refactor methods down to five lines or less, classes down to 2 pages or less (preferably a lot less), look for patterns to remove higher level duplication if it really makes the code cleaner, make sure you use separate classes for factories.
  3. Repeat until your top level classes have an excessive number of parameters (say 8+).

You’ve probably finished by now. If not, look up the dependency injection pattern…

  1. Create (only) your top level classes with a dependency injector.

Then you can repeat again…

  1. Implement another thread of a use case any old how.
  2. Refactor methods down to five lines or less, classes down to 2 pages or less (preferably a lot less), look for patterns to remove higher level duplication if it really makes the code cleaner, make sure you use separate classes for factories, pass the top level dependencies (including the factories) via DI.
  3. Repeat.

At any stage in this heuristic you will probably want to take a look at test driven development. At the very least it will stop regressions while you refactor.

It’s a bit long, but I use this heuristic all the time. I suspect that with minor variations, so do most of the people on this forum.

yours, Marcus

Identifying what your models should return is also key. Dealing with databases will normally return true/false or the insert id but if you need to return data then what type you need to return can make or break your app design.

If you need to return a JSON for consumption by a controller ( which could be for an custom API for an iPhone app or ‘dumb site’) or send back an associative array of a database query that will be sent to a classic fat-site view for iteration. (fat site = central website with all the models pulling right off the database into however you use the data)

Do you even need a design pattern for that? Build it how it makes sense, and if it happens to be in an existing design pattern all the better for the person that takes over for you later down the road.

In my experience, the patterns are usually how the MVC framework … work. For instance, a singleton would explain the CodeIgniter instance. You only want it one time so when you build a library you get the CI instance through your controller or through a magic method ( __get() for php 5 in this case). That way you can call CI libraries from within your own library without spawning a new CI instance.

I deal with databases, and I am not sure I’d ever use a singleton for any of my models. At that point you’d really want to look into some sort of ORM like doctrine. That can be limiting and full of overhead, where a good Base Model ( a class that handles CRUD functions using simple active-record methods of a MVC library ) can be just as powerful, customizable and use less overhead. I build my Base Models for CodeIgniter in a very metadata way. My Model that extends my Base Model will feed in all the meta data values like join tables and a default select statement.

Note: these examples are specific to CodeIgniter. $this->db is a CI library for ActiveRecord pattern for database interaction.

class MY_Model extends Model {

    /**
    | model_schemabase model_schema initiated from child.
    |
    | @param associative array
    |
    */
    protected $model_schema;

    public function __construct() {
        parent::Model();
    }

    /**
    | Active Record Delete method.
    |
    | @param string
    | @return boolean
    |
    */
    public function delete($qry = NULL) {
        return $this->db->delete($this->model_schema['table'], $qry);
    }

    /**
    | Active Record Create method.
    |
    | @param associative array
    | @return boolean or integer
    |
    */
    public function create_and_return_id($data = NULL) {
        if( ! $this->db->insert($this->model_schema['table'], $data)) {
            return FALSE;
        }

        if( ! $id = $this->db->insert_id()) {
            return FALSE;
        }

        return $id;
    }

    /**
    | Active Record Get that accepts a query, limit and offset
    |
    | @param string x 3, 1 bool
    | @return resource object or array depending on bool arg
    |
    */
    public function get($qry = NULL, $limit = NULL, $offset = NULL, $return_array = FALSE) {
        $this->db->select($this->model_schema['select']);

        if($this->model_schema['join']) {
            foreach($this->model_schema['join'] as $key => $value) {
                $this->db->join($key, $value, 'left');
            }
        }

        if($limit) {
            if($offset) {
                $this->db->limit($limit, $offset);
            } else {
                $this->db->limit($limit);
            }
        }

        if( empty($this->model_schema['where'])) {
            if($qry) {
                $this->db->where($this->model_schema['table'] . '.id', $qry);
            }
        } else {
            foreach($this->model_schema['where'] as $key => $val) {
                $this->db->where($key, $val);
            }
        }

        if( ! empty($this->model_schema['order_by'])) {
            $this->db->order_by($this->model_schema['order_by'], "asc");
        }

        $query = $this->db->get($this->model_schema['table']);

        if( ! $query->num_rows() > 0) {
            return FALSE;
        }

        if( ! $return_array) {
            return $query->result();
        } else {
            return $query->result_array();
        }
    }
}

<?php if( ! defined('BASEPATH')) exit ('No direct script access allowed');

class Products extends MY_Model {


    protected $model_schema = array (
        'table' => 'products',
        'join' => array(
            'vendors' => "products.vendor_id = vendors.id",
            'product_types' => 'products.product_type_id = product_types.id',
            ),
        'select' => 'products.id, products.vendor_id, products.item, products.is_active, products.picture, products.description, product_types.type, vendors.company'
    );

    function __construct() {
        parent::__construct();

    }
}

There are other methods in the base model that like the get() that would take the join associative array into consideration. You could even add non-Base methods to your child model that call parent methods for specific needs:

function get_dropdown() {
        $this->model_schema['select'] = 'products.id, products.item';

        return parent::get();
    }

That would go into the Products class that extends the base. You then get the ability to change the select value, in this case for a dropdown populator, while not having to rewrite the get method.

Heck, if you plan on doing a application where other counties, countries or providence might want to buy/or purchase services it from your employers… you should look into using something like mongoDB ( for regional speed ) and build an API system. Then your MVC app will just be a central application to consume bits sent back from the API.

It really just depends on your vision. Is this an online version of a desktop oriented app, or is this going to be dare I even use the ridiculous term web 2.0. Then go from there.

I will reduce my big previous post to a smaller one containing the doubts:

When we say, programming from “top” to “bottom” and use comments, does that mean that we should grab what we expect to be our application methods, and start creating them, by comment them what they will do ?

I’ve seen some classes handled things that I would not classified as “real world things”. (like validation, login, connection…)

Does that mean that we should abstract a lot, but not everything?
Our how do we decide what should we and what shouldn’t we, abstract ?

Regards to all, :slight_smile:

Thanks a lot. It may seem a simple question, but it has really make me thinking about that. More clear now.

About the first question, the more I think about it, the more I notice that it should be a nice way of doing things. List the methods, and objects that we want, and then try to build their skeleton by using phpDOC todo and desc for describing how/what will they do.

I haven’t provide the database physical model, because it isn’t in english. (forgot). :s

Regards, and thanks for all your replies. I have certainly clear a lot here. :slight_smile:

You’re supposed to wait for the 2nd, 3rd and 4th part!!! Not written them yet.

To organise your objects, get your brief and outline all your nouns. From there you can whittle down the REAL objects. For example, the noun “Customer” is probably going to be a child object of “User” etc. It’s using logical thinking. Once you’ve done that - you have your objects! I usually start and the middle with the spec and a load of objects, then work to the high level. Then when you’re developing, you’ll get a much better view of bottom level objects that extend your original view.

I would suggest not using MVC. It’s a weird pattern to really get your head around and there are much better architectural solutions out there… You can still use Zend Framework as it’s an extensive library as well.

@webaddictz: That describes perfectly what I’m leaving on, day by day. :slight_smile: I overpass a dead line that more or less, earlier, I was able to handle ok, using procedural.

I don’t have procedural experience. (just a bit), because when I started, I start listen others talked about OOP way of doing it.

Still, I will use a lot of things that I don’t grasp.
It will be bad, sometimes even worst then the old way of doing things, but that’s a path that I take.

Anyway, I’m aware of those bad summers I had several :s But they are getting less bad. :smiley:

Probably this, with the other book of the same series about design patterns, can give me way to start.

But this post is about the “next step”. Is about grabbing some database UML and convert that into Objects on a conceptual way. What we do with those? Well… we start creating those objects. By looking to that list. :smiley:
Why? Because they will be a LOT and I cannot have all that on my head.

And how they will be related, or how should we relate those? That’s another history that we need to grasp.

Read the UML and try to fill some CRC cards? Could be a way?

Regards,
Márcio

You’re more than allowed to disagree, I know I don’t always agree with you, but that keeps the discussion alive ey? :slight_smile:

Anyway, I’ve been there once or twice. The first time I encountered the problem was when I just started seeing the (huge) benefits of Object Oriented Programming and was asked to give an estimate on a rather big application. I decided OO was the way to go, and did an estimate which had to be sharp, because there was competition and we were just starting.

Skip ahead a few months, worst… summer… ever. What had happened is that I gave an estimate on how much time it would take me using plain ol’ vanilla PHP, which I was rather good at and even had a library for (I did use templates, database classes and more like that at the time). My enthusiasm for OO hadn’t gone away since the start of the project so I carried on trying to write everything in objects.

Skip ahead a month past deadline, and the project was finally in beta. Well, sort of, anyway. It had become a monstrosity in both size and complexity, so bug fixing took me hours, and they were all ugly hacks.

Ugh. That’s when I swore never, ever trying to implement something that I don’t grasp fully on a project that’s still in development. I can actually say I’ve learned it the hard way, and that’s a really good way to learn, but I figure it might be helpful to not let other people make the same mistake. It has cost me money, and a lot of it.

Of course, the leap from procedural programming to OO programming is a big one to take, and a very real example of a technique you don’t want to switch to whilst not fully grasping it, but only one of the examples. Fun fact: the project I did after the one that failed was written procedurally, not OO. I used OO in my pet projects, kept on reading books, fora and blogs, and now I can say that OO actually helps me, instead of holding me back.

That’s kind of the point I was trying to make: don’t use it if you don’t fully grasp it, and you’re not sure you actually grasp it until you’ve used it. Experimenting is how you learn, so don’t stop doing that, but I’d suggest you don’t do it on anything where you actually have to deliver after a certain amount of time. The problem with experimenting is that it’s damn hard to figure out how long you’ll be experimenting for, which makes the planning harder.

Exactly.

I can upload the database UML structure. :smiley: If someone else steals it and do better, I will be more then glad. :wink:
I will try to provide that later this night.

I see… but before that, I need a way to identify what those functions will be, so that would be the next step after the interesting link provided earlier.

Nice. And it’s the way we organize them, that will allow us, later on the process, to start seeing the design patterns… right?

Yes. I’m fairly newbie on all of this, and design patterns are hard to start with. More projects will give me a more experience, and with hard work, maybe I can be able to start see them. That’s exactly the thing: at the moment, I can’t see them.

Np. That’s what I do for everything, or almost, and that’s the main reason why my projects take so looong to be accomplished. :s

Regards,
Márcio

Thank you all.

That’s a very interesting link, and that is the kind of information I’m looking for to discuss here. I mean, “Analyse your database structure” - yes of course, but precisely how can that be done? “Organize your objects” - ok, sure, but, precisely, how can we do that…

Life of a malformed newbie is hard. :slight_smile:

I’m no expert on patterns as such…but most of the time identifying component or object needed is always part of a headstart to a project i’m working on.

Like below posted in a blog by a developer…

http://kirstiehaxby.com/?p=116

You don’t, I don’t either. I don’t see a functionality that has to be written and think that I could use pattern X or Y for that. I start writing the functionality, without repeating myself and with the most readable solution I can write, and patterns just emerge. Once I start refactoring, the pattern to use is often painfully obvious, but I don’t start by figuring out what patterns I should use in an application, they grow in.

I’ve used patterns all my life, I just didn’t call them Design Patterns, because I didn’t know that such a thing had a name. It was just my regular way of solving a specific problem.

So don’t. I’ve been in the game long enough to learn a very important thing: don’t try to put stuff in your software you’re just beginning to learn. I’ve bumped my head on this one dearly a few times, and you’re better off with using your old techniques. Otherwise, there is no way you can have a viable planning.

Of course, you shouldn’t stop learning, and you shouldn’t stop reading: that’s the very reason I’m on this forum. Just don’t try to implement things you’ve just encountered in your software, or your planning will be ruined. For this specific reason, I have a few pet projects, which don’t have deadlines or customers, or even users, just to see how the thing I just learned works out in practice.

Agreed. lastcraft is doing by coding, what sunwukung and I do in program comments, but you’ll note the strong similarities. Start with what you know. Start at the top (meaning start with the most general statements) and work your way down (to more and more detailed statements) Find duplicate code aggressively and stick it in a utility function which you can call. And as you’re working you will see opportunities to rewrite your program so that it works better; sometimes this will involve seeing a particular pattern that you can use, but frequently it’s just about identifying a better abstraction which becomes an important new class or encapsulating part of a function to make the application read more simply. And a big part of this is to repeat the process over and over and over, because you CAN’T see all those things the first time through (or the second, or the third).

:slight_smile: Sorry, I guess I think too much from a programmer’s perspective sometimes. When I said “real world” I meant what you said much better. In fact, if you look at most of the accepted design patterns, they work so well because they take things which non-programmers think of as “technical”, or that most developers would execute as a simple data type and convert them into full fledged classes. This requires more coding, but brings a lot more power to those constructs and when configured correctly (like the factory pattern, strategy pattern, command pattern, and many other less formalized cases) allow you to do some really wicked cool stuff.

When I said “real world”, what I probably should have said was this… when I’m programming, I have in my head pieces of the application design. Each of those pieces is what I call an abstraction - it’s a mental concept that lives in my head that I use to really understand my program whether that’s something tangible like a user, something abstract (as in quite literally an abstract factory), or something highly technical like a queue request using the command pattern. The thing I love about OOP is that classes give me a simple way to translate my mental model into code. Each of those abstractions simply becomes a class. Then all the code and data that I need to use to accomplish my tasks simply goes into the most appropriate class which makes it very easy later to remember exactly where you put things, and where to go looking for code that you need to modify.

yeah - the idea that objects should represent “real world” thing is a failed attempt at pedagogy. A proper object oriented application should have lots of objects that represent highly abstract and technical concepts. But make sure that the concepts are clearly understood (by the programmer). If you have problem naming something, it should be a warning signal.

+1

Oh definitely, I (and this is of course entirely subjective) just find it more beneficial to experiment with something where the brief isn’t written by me. In the past I’ve implemented new ideas in very small scale systems which I think will deal with 99% of cases then come to a client meeting and a client will want something I hadn’t even considered and I’ll have to rethink a large chunk of the problem.

I think it’s a question of scale, both of the project at hand (if it’s a small project which isn’t likely to be re-visited often, it doesn’t really matter if it’s going to cause a bit of a maintainability problem down the line) and how much of a change to the existing code it is. Generally the type of things I’m talking about here aren’t as huge as going from procedural to OO, but experimenting with quite specific things like ActiveRecord vs DataMapper and different template implementations. Generally things which are interchangeable within an existing code base rather than rewriting 95% of the library code, which is not something I’d ever recommend doing all at once even if your library code is tiny.

I’m not sure I completely agree with your final sentiments there webaddictz, for me the easiest way to understand the reasoning behind a knew piece of knowledge is to try it myself and usually, given a real world problem it’s easier to understand the thinking behind it. If I didn’t put things I was just learning into my software, a) I wouldn’t enjoy my job nearly as much, and b) my rate of learning would be hugely slowed.

Ok, don’t try new ideas on large, tight deadline client sites but for smaller and less important jobs sometimes it’s fun to experiment and it means when you get to the bigger, more important projects you have a better understanding and can apply the new idea properly.

I prefer implementing new ideas on real projects with real deadlines (though not short ones :p) it forces me to think through the problem and overcome any issues created by attempting to implement it.

It’s probably not a good idea to implement more than one new idea at a time though :wink: