Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Interfaces in Perl5 at The Perl Conference 2019...
Search
Kenta Kobayashi
June 17, 2019
Technology
0
2.8k
Interfaces in Perl5 at The Perl Conference 2019 in Pittsburgh
Kenta Kobayashi
June 17, 2019
Tweet
Share
More Decks by Kenta Kobayashi
See All by Kenta Kobayashi
Tシャツに書かれたコードを読む
kfly8
0
1.2k
Introduce Sub::Meta
kfly8
0
43
研修はイベントでなくコミュニティ作り
kfly8
0
1.2k
明日からできる新人のオンボーディングガイド
kfly8
0
770
メンター成長のためのふりかえり会
kfly8
0
1.2k
経験から効率よく学習する
kfly8
0
260
Interfaces in Perl5
kfly8
1
910
p5-Lodash!
kfly8
2
790
PPRとKeyword::Simpleと あとVariable::Declaration
kfly8
0
150
Other Decks in Technology
See All in Technology
権威ドキュメントで振り返る2024 #年忘れセキュリティ2024
hirotomotaguchi
2
760
MLOps の現場から
asei
7
650
re:Invent をおうちで楽しんでみた ~CloudWatch のオブザーバビリティ機能がスゴい!/ Enjoyed AWS re:Invent from Home and CloudWatch Observability Feature is Amazing!
yuj1osm
0
130
フロントエンド設計にモブ設計を導入してみた / 20241212_cloudsign_TechFrontMeetup
bengo4com
0
1.9k
サイバー攻撃を想定したセキュリティガイドライン 策定とASM及びCNAPPの活用方法
syoshie
3
1.3k
普通のエンジニアがLaravelコアチームメンバーになるまで
avosalmon
0
110
TSKaigi 2024 の登壇から広がったコミュニティ活動について
tsukuha
0
160
Oracle Cloud Infrastructure:2024年12月度サービス・アップデート
oracle4engineer
PRO
1
210
スタートアップで取り組んでいるAzureとMicrosoft 365のセキュリティ対策/How to Improve Azure and Microsoft 365 Security at Startup
yuj1osm
0
230
pg_bigmをRustで実装する(第50回PostgreSQLアンカンファレンス@オンライン 発表資料)
shinyakato_
0
100
多領域インシデントマネジメントへの挑戦:ハードウェアとソフトウェアの融合が生む課題/Challenge to multidisciplinary incident management: Issues created by the fusion of hardware and software
bitkey
PRO
2
110
GitHub Copilot のテクニック集/GitHub Copilot Techniques
rayuron
37
15k
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
5
450
VelocityConf: Rendering Performance Case Studies
addyosmani
326
24k
RailsConf 2023
tenderlove
29
940
The World Runs on Bad Software
bkeepers
PRO
65
11k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Six Lessons from altMBA
skipperchong
27
3.5k
Designing for humans not robots
tammielis
250
25k
A Philosophy of Restraint
colly
203
16k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.9k
Transcript
Interfaces in Perl5 kobaken a.k.a @kfly8 The Perl Conference 2019
#TPCiP
me • kobaken a.k.a @kfly8 • leader Gotanda.pm • orgnize
YAPC::Tokyo 2019
None
None
None
None
None
None
None
None
I ❤ Perl
Interfaces in Perl5
DBI
my $dbh = DBI->connect(...); my $items = $dbh->selectrow_arrayref(…);
Unified Interface independent of datastore
Unified Interface provides values
Limitation makes value
Agenda 1.DEMO & Features 2.Goal 3.Example: TODO app 4.Internal 5.Performance
Function::Interface is Java-like interface
DEMO
Features of Function::Interface 1.Typed interface definition 2.Check at compile time
What is Goal ?
To maintain large Perl apps
Interface is good for large apps
1. Be easier to fix implementation
2. Stable dependencies
Goal • To maintain large apps. • Interface is good
for large apps 1. Easy to fix implementation 2. Stable Dependencies
Example: TODO app
Case: “Inheritance”
package TodoRepository; use parent qw(DBI); sub new { my $class
= shift; $class->connect(…); }
package TodoRepository; … sub select { my ($self, $user_id)
= @_; $self->selectall_arrayref( ‘SELECT * FROM todos WHERE user_id = ?’, $user_id ); }
package TodoApp; use TodoRepository; my $repo = TodoRepository->new;
package TodoApp; use TodoRepository; my $repo = TodoRepository->new(…); sub my_todo_list
{ my $self = shift; my $todos = $repo->select($self->user_id); return $self->render($todos); }
TodoApp TodoRepository DBI TODO table
TodoApp TodoRepository DBI TODO table
TodoApp TodoRepository DBI TODO table Unstable Dependencies
package TodoApp; use TodoRepository; my $repo = TodoRepository->new; sub evil_method
{ $repo->do(“ANY QUERY!!!!”); }
package TodoApp; use TodoRepository; my $repo = TodoRepository->new; sub evil_method
{ $repo->do(“ANY QUERY!!!!”); } Too many features
easy to test?
my $mock = mock TodoRepository => ( select => sub
{ … } ); my $app = TodoApp->new; test $app->my_todo_list;
my $mock = mock TodoRepository => ( select => sub
{ … } ); my $app = TodoApp->new; test $app->my_todo_list; messy to test
Problems of “Inheritance” case 1.Unstable dependencies 2.Too many features 3.messy
to test
“Role” case
package TodoRepositoryInterface; use Moo::Role; requires qw(select);
package TodoRepository; use Moo; with qw( TodoRepositoryInterface ); has dbh
=> ( isa => ‘DBI::db’ );
package TodoRepository; use Moo; with qw( TodoRepositoryInterface ); has dbh
=> ( isa => ‘DBI::db’ );
package TodoRepository; … sub select { my ($self, $user_id) =
@_; $self->dbh->selectall_arrayref( ‘SELECT * FROM todos WHERE user_id = ?’, $user_id ); }
package TodoApp; use Moo; has todo_repo => ( is =>
‘ro’, does => ‘TodoRepositoryInterface’ );
package TodoApp; … sub my_todo_list { my $self = shift;
my $repo = $self->todo_repo; my $todos = $repo->select($self->user_id); return $self->render($todos); }
TodoApp TodoRepository DBI TODO table TodoRepositoryInterface
TodoApp TodoRepository DBI TODO table TodoRepositoryInterface NOT!
TodoApp TodoRepository DBI TODO table TodoRepositoryInterface more stable
Problems of “Inheritance” case 1.Unstable dependencies 2.Too many features 3.messy
to test
package TodoApp; use Moo; has todo_repo => ( is =>
‘ro’, does => ‘TodoRepositoryInterface’ ); sub evil_method { $todo_repo->do(“ANY QUERY!!!!”); }
package TodoApp; use Moo; has todo_repo => ( is =>
‘ro’, does => ‘TodoRepositoryInterface’ ); sub evil_method { $todo_repo->do(“ANY QUERY!!!!”); }
package TodoApp; use Moo; has todo_repo => ( is =>
‘ro’, does => ‘TodoRepositoryInterface’ ); sub evil_method { $todo_repo->do(“ANY QUERY!!!!”); } Necessary and sufficient features
Problems of “Inheritance” case 1.Unstable dependencies 2.Too many features 3.messy
to test
easy to test?
package TestTodoRepository; use Moo; with qw( TodoRepositoryInterface ); sub select
{ … }
package TestTodoRepository; use Moo; with qw( TodoRepositoryInterface ); sub select
{ … } Be easier to test
Problems of “Inheritance” case 1.Unstable dependencies 2.Too many features 3.messy
to test
no problem at all?
package TodoRepositoryInterface; use Moo::Role; requires qw(select); sub surprised_method { ..
do anything }
package TodoRepositoryInterface; use Moo::Role; requires qw(select); sub surprised_method { ..
do anything } Implementation reusable
package TodoRepositoryInterface; use Moo::Role; requires qw(select);
select($id) ? select(id => $id) ? select({ id => $id
}) ?
select($id) # => arrayref of Todo ? # => iterator
of Todo ?
select($id) # => arrayref of Todo ? # => iterator
of Todo ? Ambiguous interface input / output
Problems of “Role” case 1.Implementation reusable 2.Ambiguous interface input /
output
“Function::Interface” case
package TodoRepositoryInterface; use Function::Interface; use TodoTypes; method select(UserID $user_id) :Return(ArrayRef[Todo]);
Problems of “Role” case 1.Implementation reusable 2.Ambiguous interface input /
output
package TodoRepositoryInterface; use Function::Interface; use TodoTypes; method select(UserID $user_id) :Return(ArrayRef[Todo]);
sub surprising_method { … do anything }
package TodoRepositoryInterface; use Function::Interface; use TodoTypes; method select(UserID $user_id) :Return(ArrayRef[Todo]);
sub surprising_method { … do anything }
Problems of “Role” case 1.Implementation reusable 2.Ambiguous interface input /
output
package TodoRepository; use TodoTypes; use Function::Interface::Impl qw( TodoRepositoryInterface ); has
dbh => ( … ); method select(UserID $user_id) :Return(ArrayRef[Todo]) { … }
package TodoApp; use Moo; use TodoTypes; has todo_repo => (
isa => ImplOf["TodoRepositoryInterface"], ); sub my_todo_list { … }
Looks Good!
Internal
requirements 1.function implementation 2.function interface 3.check if interface is implmented
4.interface type
1. function implementation
Function::Parameters • subroutine signatures • developed by MAUKE
use Function::Parameters; use Types::Standard -types; fun add(Int $a, Int $b)
{ return $a + $b }
my $info = Function::Parameters::info(\&add); $info->positional_required; # => Int $a, Int
$b
Function::Return • specify function return types • created by myself
sub add :Return(Int) { 3.14 } add(); # ERROR! Invalid
type
my $info = Function::Return::info(\&add); $info->types; # => Int
Appendix about Function::Return
sub multi :Return(Num, Str) { 3.14, ‘message' } my ($pi,
$msg) = multi();
sub multi :Return(Num, Str) { 3.14, ‘message' } my ($pi,
$msg) = multi(); my $count = multi(); # ERROR!
requirements 1.function implementation 2.function interface 3.check if interface is implemented
4.interface type
2. function interface
Function::Interface • Keyword::Simple • PPR
Deparse fun hello() :Return(Str);
sub BEGIN { Function::Interface::_register_info({ package => ‘HelloInterface', keyword => ‘fun',
subname => ‘message', params => [], return => [&Str()]} ); }
my $info = Function::Interface::info(“HelloInterface”); $info->functions; # => hello(Str $msg) :Return(Str)
requirements 1.function implementation 2.function interface 3.check if interface is implemented
4.interface type
3.check if interface is implemented
use Function::Interface::Impl qw( FooInterface BarInterface BazInterface );
F::Parameters#info F::Return#info F::Interface#info
F::Parameters#info F::Return#info F::Interface#info
requirements 1.function implementation 2.function interface 3.check if interface is implemented
4.interface type
use Function::Interface::Types; my $type = ImplOF[‘FooInterface’]; # Foo is implements
of FooInterface my $foo = Foo->new; $type->check($foo);
requirements 1.function implementation 2.function interface 3.check if interface is implemented
4.interface type
Performance
F::I::Impl runs at compile time
F::Return has `no_check` option
Let’s benchmark
F::P + F::R + F::I F::P + F::R no_check +
F::I F::P + F::R no_check F::P Case1 Case4 Case2 Case3
F::P + F::R + F::I F::P + F::R no_check +
F::I F::P + F::R no_check F::P 360653.77/s 1499189.22/s 1499189.22/s 1499189.22/s Case1 Case4 Case2 Case3
$BTF $BTF $BTF $BTF
Conclusion
Features of F::Interface 1.Typed interface definition 2.Check at compile time
Goal • To maintain large apps. • Interface is good
for large apps 1. Easy to fix implementation 2. Stable Dependencies
Internal • function implementation • Function::Parameters + Function:\:Return • function
interface • Keyword::Simple + PPR • compare meta infos at compile time
Performance • The same speed as using only F::Parameters •
Function::Interface::Impl runs at CHECK phase • Function::Return has `no_check` option
Questions?
Thank you!