OOP内聚/耦合混淆

I have a question regarding the correct way of splitting objects.

Say I have two objects, such as Tool and Technology. A Technology can have multiple Tool objects associated with it, but is it considered low cohesion/tight coupling for a Technology to know directly about a Tool? Is it bad practice to have the Technology object to contain an array of Tool objects or should there be some sort of third class that would tie them together?

Tool
private id;
private title;

Technology
private id;
private title;
private tools;

Could you provide a simple overview of how it would be best to associate the to objects with one another? At first glance it seems like it would be ok to me, but would it really be appropriate for a Technology object to have getter/setter methods for adding Tools?

If Technology needs Tool objects, there's nothing wrong with it keeping them.

If the Tools are relevant to the Technology object state, than it should contain them inside of it.

Relevant possible methods:

public addTool(Tool $tool);
public removeTool(Tool $tool);
public removeToolByIndex($index);
public getToolFromIndex($index);

I am in no way an expert on OOP, but I would say that it depends on your domain. If your domain is dealing with technologies wich in turn deal with tools, then I'd say it's ok to have a tools array in a technology. What I'd do is have every tool object conform to the same interface, so that any technology can have any tool.

Also, from what I learned, I think that decoupling is important when you are crossing layers (domain, persistence, service layer ...). So a layer should not depend on another layer, but your domain objects can depend on one another.

If you are modeling a domain where an entity depends on another, then the objects will also depend on one another (if a technology is useless without it's tools, then it depends on them). To take the common Car/Wheel/Driver example, a car depends on both the wheel and the driver in real world, so the objects will to, because it is completely useless if they are missing.

I hope this makes sense, and if I got it wrong, then I'll learn something too from someone else.

Example you gave is many to many association so its better to use 3d object to represent association. If its on way(one to many) then simple composition as you mentioned would be fine.

Below is sample code, few improvements that can be made in code 1. implement getter setter for Tool & technology and make variables private. 2. Use interfaces instead of classes directly for Tools & Technology. 3. Used 2 different indexes(array) in pair class to improve performance of get functions, if performance is not concern then u can just use one array.

<?php
class Technology{
    public  $id;
    public  $title;

    public function __construct($id, $title){
        $this->id = $id;
        $this->title = $title;
    }
}

class Tool{
    public $id;
    public $title;

    public function __construct($id, $title){
        $this->id = $id;
        $this->title = $title;
    }
}

class TechnologyToolPair{
    private $techIndex = array();
    private $toolIndex = array();

    //Index by id, you can replace title if u maily search by title
    public function addPair($tech, $tool){
        $this->techIndex[$tech->id]['technology'] = $tech;
        $this->techIndex[$tech->id]['tool'][] = $tool;

        $this->toolIndex[$tool->id]['tool'] = $tool;
        $this->toolIndex[$tool->id]['technology'][] = $tech;
    }

    public function getByTechnologyId($id){
        return $this->techIndex[$id];
    }

    public function getByToolId($id){
        return $this->toolIndex[$id];
    }

    public function getByTechnologyName($name){
        foreach($this->techIndex as $index => $value){
            if(!strcmp($name, $value['technology']->title)){
                return $value;
            }
        }
    }
}


$tech1 = new Technology(1, 'php');
$tech2 = new Technology(2, 'java');

$tool1 = new Tool(1, 'eclipse');
$tool2 = new Tool(2, 'apache');
$tool3 = new Tool(3, 'tomcat');

$pair = new TechnologyToolPair();
$pair->addPair($tech1, $tool1);
$pair->addPair($tech1, $tool2);
$pair->addPair($tech2, $tool1);
$pair->addPair($tech2, $tool3);

var_dump($pair->getByToolId(1));
var_dump($pair->getByTechnologyId(2));
var_dump($pair->getByTechnologyName('java'));

You should take a look at the behavior and the interaction between tool and technology, not just the data. That determines how to model in OOP. You are currently doing data modeling, and object-orientation is supposed to give a better modularization. You might want to drive the design from tests, showing how they are used.