Really nice write up, thank you! 👍
I have only one complaint, with the "Do nothing in the constructor function, Only assign properties" part.
I think in the first solution (extracting to a method) it could be called from the constructor, this is what I usually do if it is not a complicated task. This way it only runs once, and the constructor is the place where you should prepare all of your dependencies, like you said above.
The second method (expecting bootstrapping) adds a hidden dependency, as the logging will fail if the file is not present. Moving it out of the class can be a good idea (especially if it is complex), but I would move it to a Factory class, and make the FileLogger constructor only visible to that class.
I would love to hear your opinion on this.
I wrote PHP code years ago, but I forgot it does not have nested classes like Java, that is what I was referencing with "make the FileLogger constructor only visible to that class", but you can do a similar thing if you make the constructor protected and move the Factory class to the same package.
finalclassFileLogger{private$logFilePath;protectedfunction__construct(string$logFilePath){$this->logFilePath=$logFilePath;}publicfunctionlog():void{$this->ensureLogFileExists();}}finalclassFileLoggerFactory{publicfunctioncreate(string$logFilePath):FileLogger{ensureLogFileExists($logFilePath);returnnewFileLogger($logFilePath);}privatefunctionensureLogFileExists(string$logFilePath):void{if(is_file($logFilePath)){return;}$logFileDirectory=dirname($logFilePath);if(!is_dir($logFileDirectory)){// create the directory if it doesn't exist yetmkdir($logFileDirectory,0777,true);}touch($logFilePath);}}
Also, I am new here and I have no idea how to have syntax highlight :(
Yeah. You can absolutely call that in the constructor as well to make it run once on the entire object. That would be a good approach to do a sanity check before logging. Thanks for the feedback.
For the second approach with bootstrapping, the dependency is still not hidden. Just that we pass it from the bootstrap face. There are some exceptions that might happen with this, so you will need to throw some exception depending on the issue that might occur. The article just focussed on only one exception type but there are others that we can also look at.
I meant hidden as you can create a FileLogger instance without error even if you do not create the file for it, and it will only fail when the first logging takes place, not at creation time.
Really nice write up, thank you! 👍
I have only one complaint, with the "Do nothing in the constructor function, Only assign properties" part.
I think in the first solution (extracting to a method) it could be called from the constructor, this is what I usually do if it is not a complicated task. This way it only runs once, and the constructor is the place where you should prepare all of your dependencies, like you said above.
The second method (expecting bootstrapping) adds a hidden dependency, as the logging will fail if the file is not present. Moving it out of the class can be a good idea (especially if it is complex), but I would move it to a Factory class, and make the FileLogger constructor only visible to that class.
I would love to hear your opinion on this.
Can you show your proposed solution in code? I mean that of the second method, bootstrapping.
I wrote PHP code years ago, but I forgot it does not have nested classes like Java, that is what I was referencing with "make the FileLogger constructor only visible to that class", but you can do a similar thing if you make the constructor protected and move the Factory class to the same package.
Also, I am new here and I have no idea how to have syntax highlight :(
I have seen the approach as well. Thanks. So allowing the Factory object to new up the object.
For the code highlighting, you can use
3start-backticts
langauge(php, js, py, etc)
3end-backticks
Yeah. You can absolutely call that in the constructor as well to make it run once on the entire object. That would be a good approach to do a sanity check before logging. Thanks for the feedback.
For the second approach with bootstrapping, the dependency is still not hidden. Just that we pass it from the bootstrap face. There are some exceptions that might happen with this, so you will need to throw some exception depending on the issue that might occur. The article just focussed on only one exception type but there are others that we can also look at.
Great feedback.
Thank you for your answer!
I meant hidden as you can create a FileLogger instance without error even if you do not create the file for it, and it will only fail when the first logging takes place, not at creation time.
Thank you for the explanation. Very much appreciated