Yii3 Properties


(Oleg) #22

Paragraph 1:
I did not not request simplicity att all, this is you who started talking about simplicity.

Paragraph 2:
I am not talking about tool, I am talking about product. I just believe that Laravel is now leading because of marketing. this happens often in real world, this is not enough to be good, the product also need to be “sexy”/“appealing”.

Think not about CNC mill, but about brands of CNC mills. For example some brand can be known for durability, other brand for wide functionality, and another for the price. There are also brands or products for industural or small companies/home use. This is concept. You can not create a CNC mill for home using industrial concept, and Vise Versa.

You started with bikes. Think about Harley vs Ducati, in my opinion they have distinct “global concepts”


(Breg) #23

CNC mills do not need a ‘global vision’, and could not profit from it, that was my point.
Using one for several years - typical, not like a smartphone - the reliability and quality is more depending on your maintenance and attention when you use it. It is important that the various parts can easily be checked, maintained or changed - by the user. You may exchange a bearing here, a stepper motor there, or update to a new controller. After the years, it has more become a ‘Oleg84 mill’ than a ‘XYZ’ brand mill.
So this is very similar to a web framework.

About motorbikes, you chose the right examples - for your POV :slight_smile:
If you believe in a growing market for motorbikes, buy the shares from Ducati (Audi, VW) and Harley.
I had a new Ducati once, and sold it after some years, having spend many hours just to keep it running (because of lack of attention to detail in the construction; with new engines every 1…2 years).
HDs have a stupid riding position, ok for slow and straigt highways, not for eurasian streets, only for posers.
So everyone who really likes the road and the wind would prefer other brands (and old models, with simpler mechanics).


(Oleg) #24

I do not think CNC mills have a massmarket.

Bikes have. Web frameworks have.

Mass market means, in my opionon, also lot of neophites. If professionals use rational thinking, neophits are driven by emotion. Thats why Web Framework needs to have some nice “Philosophy” - to attracts new blood. When I say philosophy I do not mean “the system”, I mean more a slogan. Nike - “Just do it”. Or Communism - “Same rights and level of living for everyone”. But then we can unpack this short stories in a whole philosophy. But this is only one small aspect of a big thing, it was just an example how “Global vision” could be usefull.


#25

@olegl84 @ED42 Please move this discussion to email or slack - it has nothing to do with this topic.


(Oleg) #26

In my opinion the current biggest problem of Yii is that it is not considered as suitable for big projects. And this is not far from true.


(Oleg) #27

yes, It went too far :slight_smile:


(Breg) #28

Sorry, the discussion is still about the core topic:
“The thing is that I don’t want Yii to continue being closed community. … Yii 3 is meant to work with any PHP classes without wrappers and to reuse PSR-compatible libraries.”

@Oleg, I don’t see Yii as a product in a market. It’s free.
Other frameworks have collected money on the investor markets and play or mimic the startup game. Their choice, but not a neccessary property of a web framework.


(Mike) #29

I was just going to open an issue for yii3 for a way how properties could work, when I found out that things there changed quite drastically since yii2. So let’s try here:

I also think that a trait for properties could be useful somewhere in the core. Here’s my suggestion.

Problem

I often find myself writing a pattern like this:

protected $_foo;

public getFoo()
{
    if ($this->_foo === null) {
        // Initialize $this->_foo here:
        $this->_foo = 'initial value';
    }
    return $this->_foo;
}

public function setFoo($value)
{
    $this->_foo = $value;
}

This pattern is:

  • repetitive
  • bloats the class with 2 methods per property

Proposal

I therefore suggest an alternative way of defining these properties. The above would be equivalent to:

public function props()
{
    return [
        'foo' => function() {
            // Initialize value here
            return 'prop value'; 
        },
    ];
}

For more complex properties an alternative array syntax can be used:

public function props()
{
    return [
        'bar' => [
            'readOnly' => false, // default
            'init' => function() { 
                return 'prop value'; 
            },
            'validate' => function ($value) {
                // Either return false or throw exception for invalid values
            },
            // more options ??
    ];
}

Pros

  • Less repetition
  • Less code and thus less bloat
  • All properties are defined clearly at a single location

(Alexander Makarov) #30

You forgot property annotations you need to have in order to get IDE autocomplete.


(Mike) #31

Can’t we add them in the class comment header as usual?

/**
 * ....
 *
 * @property string $foo some foo for bar
 */

(Alexander Makarov) #32

We can. I’m pointing to “less” points.

In case of plain class that’s:

class Post
{
    private $title;

    public function __construct(string $title = '<please write some text>')
    {
        $this->validateTitle($title);
        $this->title = $title;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function setTitle(string $title): void
    {
        $this->validateTitle($title);
        $this->title = $title;
    }

    private function validateTitle(string $value)
    {
        if (mb_strlen($value) > 255) {
            throw new \Exception('invalid!');
        }
    }
}

In case of your variant it’s:

/**
 * @property string $title
 */
class Post
{
     use PropertyTrait;

     protected $_title;

     private function properties(): array
     {
         return [
             'title' => [
                 'validate' => function ($value) {
                     if (mb_strlen($value) > 255) {
                          throw new \Exception('invalid!');
                     }
                 },
                 'default' => function() {
                     return '<please write some text>';
                 }
             ]
         ];
     }
}

First variant is a bit more verbose but is way less magical.


#33

Not really. With getter and setter you also have 2 methods which could be part of interface for example. And syntax is clear and obvious, while props() approach is another magical solution which needs to be learned.

In general I would recommend to NOT use magic attributes whenever possible. They may look like a great idea at first look, but the bigger the project, the more WTFs you will get. Using getters and setters directly usually gives less confusion (for both - programmers and SCA tools) and saving 3-5 chars is not worth the trouble.


(Mike) #34

Well I agree to all you said. But on the other hand this means that Yii 3 will be quite different from all its predecessors. In my view one of Yii 1 and 2’s goals was to let you write code that keeps boilerplate at a minimum. Remember one of its marketing claims was “Less noise - more signal”. I liked that a lot.

Looking at Yii 3 I understand the motivations and goals (SOLID, GRASP, etc.) and also think that’s the way to proceed. But this also comes at a cost: It often means that code get more “java-ish” which equals to more noise in your code. I’m curious if this can be solved so that we can keep the Yii feeling we all like.

On a sidenote: If magic methods are avoided (which I can understand), how will this affect ActiveRecord? With PRADO (Yii’s predecessor) we had to define all DB columns as public properties of your class. IMO this would be an acceptable tradeoff. Or will there be any AR implementation in Yii 3 at all?


(demonking) #35

Because of AR, at the moment no implementation are planned.

Discussion : Using Cycle ORM

Reason : Using Cycle ORM


#36

I wouldn’t say that using getter explicit is a noise. It is actually signal - it shows you what is really happening. For example it is quite strange that you can’t use $this->someArray['someKey'] = $someValue;. But it becomes more obvious if you write it as $this->getSomeArray()['someKey'] = $someValue;.

In general I don’t think that magic attributes are that important to keep “Yii feeling”. I would be more concerned about removing some known patterns (Yii::$app - it may be ugly, but is is really convenient and easier to understand and control in small projects) or parts of original framework (URL manager, AR, console).


(Lazarevic Ivica) #37

I hate writing Java classes with bunch of trivial getter and setters. Also I hate Java for spending more time configuring than programming. I hope Yii3 is not following Java path.


(Alexander Makarov) #38

I am as well :slight_smile: Will try to avoid unnecessary boilerplate where possible but not at the cost of clarity of what actually happens.

Active Record is an exception there. Can not be done without some magic in case we don’t want to define properties manually.

Maybe.

Yii::$app is a bad and convenient thing at the same time. It is extremely easy to misuse resulting in testing and maintenance hell. In your apps you’ll be able to do it easily if needed though by defining a global class holding container right in index.php.

Current URL manager is different but porting old good one is possible. It is not a priority for me personally though since interface is in place and it works by leveraging FastRoute.

As for AR and console, sadly, I don’t have enough time to port these myself. But if there will be someone willing doing that, I’ll help with reviews, directions and will gladly accept it as part of the framework.


#39

That is understandable, but you should really ask yourself what is the point of this framework. For me Yii was some kind of balance between Laravel (which allows you to write unmaintainable code really fast) and Symfony (which is SOLID and promotes “right way” of doing things, but at cost of simplicity). Yii 2 is simple and easy to understand, without unnecessary abstractions and ceremonies, but it still scales quite well and you can build big applications without pulling hair out of your head.

In Yii 3 my two favorite parts of the framework (routing and DB layer) are gone, and framework lost much of its simplicity. It is much more like Symfony now. And it is not necessary a bad thing, but if I would need a Symfony-like framework, I would choose Symfony instead of Yii 3. I’m not feeling like Yii 3 have some killer-feature that could change that…


(Alexander Makarov) #40

Yii 3 moved slightly away from magic and fragility that were present in Yii 2: properties (magic), behaviors (magic), lack of encapsulation (fragility), ability to affect any application component from anywhere while the components were not designed for such use (fragility). It was not bad at all in skilled hands of developer who read the guide, checked source code and memorized conventions but often was disastrous in hands of less skilled developer.

Yii 3 is now uses common overall PHP practices almost without magic and fragility present. Yes, it’s more verbose compared to Yii 2. It contains less complexity than either Yii 2 (because less magic) or Symfony (because no complicated compilation, caching or config present). There are no unnecessary abstractions (if there are any, please report these as bugs). It should scale much better than Yii 2 did because testing is easier and because it prevents practices that certainly lead to less maintainable code.


#41

There was always magic cache in Yii 2 (DB schema cache, especially annoying in AR context), and Yii 3 introduces composer-config-plugin for automagic configuration.

I already raised my concerns about cache component, without any effect. There is Yiisoft\Cache\CacheInterface, but it is not implemented by cache backends (like ArrayCache). So now we have Yii cache components, which require a separate layer of abstraction (Yiisoft\Cache\Cache decorator) so they could behave as Yii cache component. ArrayCache could implement Yiisoft\Cache\CacheInterface directly, so there would be no need for decorator - there is nothing wrong with having PSR implementation with extra functionality.

Cache component was the only one I reviewed, but it really made me worry how pragmatic Yii 3 will be. Refactoring of this component made it a lot more complicated, harder to use and increased code duplication.