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
3k
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
Perlの生きのこり - エンジニアがこの先生きのこるためのカンファレンス2025
kfly8
4
2.4k
Tシャツに書かれたコードを読む
kfly8
0
1.3k
Introduce Sub::Meta
kfly8
0
65
研修はイベントでなくコミュニティ作り
kfly8
0
2.1k
明日からできる新人のオンボーディングガイド
kfly8
0
830
メンター成長のためのふりかえり会
kfly8
0
1.3k
経験から効率よく学習する
kfly8
0
430
Interfaces in Perl5
kfly8
1
960
p5-Lodash!
kfly8
2
830
Other Decks in Technology
See All in Technology
あなたの声を届けよう! 女性エンジニア登壇の意義とアウトプット実践ガイド #wttjp / Call for Your Voice
kondoyuko
4
410
Agentic Workflowという選択肢を考える
tkikuchi1002
1
490
データプラットフォーム技術におけるメダリオンアーキテクチャという考え方/DataPlatformWithMedallionArchitecture
smdmts
5
620
Navigation3でViewModelにデータを渡す方法
mikanichinose
0
220
地図も、未来も、オープンに。 〜OSGeo.JPとFOSS4Gのご紹介〜
wata909
0
110
AWS Summit Japan 2025 Community Stage - App workflow automation by AWS Step Functions
matsuihidetoshi
1
250
PHPでWebブラウザのレンダリングエンジンを実装する
dip_tech
PRO
0
200
「Chatwork」の認証基盤の移行とログ活用によるプロダクト改善
kubell_hr
1
140
TechLION vol.41~MySQLユーザ会のほうから来ました / techlion41_mysql
sakaik
0
180
PostgreSQL 18 cancel request key長の変更とRailsへの関連
yahonda
0
120
Welcome to the LLM Club
koic
0
160
AWS CDK 実践的アプローチ N選 / aws-cdk-practical-approaches
gotok365
6
710
Featured
See All Featured
Git: the NoSQL Database
bkeepers
PRO
430
65k
Making Projects Easy
brettharned
116
6.3k
Agile that works and the tools we love
rasmusluckow
329
21k
What's in a price? How to price your products and services
michaelherold
246
12k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.3k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
930
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Building Adaptive Systems
keathley
43
2.6k
The Language of Interfaces
destraynor
158
25k
Writing Fast Ruby
sferik
628
61k
4 Signs Your Business is Dying
shpigford
184
22k
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!