V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gitrebase
V2EX  ›  程序员

大家喜欢用 ORM 还是直接写 SQL

  •  1
     
  •   gitrebase · 309 天前 · 18268 次点击
    这是一个创建于 309 天前的主题,其中的信息可能已经有所发展或是发生改变。

    OP 主要用的 Java 和 Go ,但是感觉这俩主流语言的 ORM 框架( JPA 、GORM )都不如 C#、Python 的 ORM 好用( JOOQ 、ent 、XORM 感觉国内用的还是有点少),而 SQL / SQL builder ( JdbcTemplate 、sqlx )在动态条件查询时需要在代码里拼 SQL 字符串也有点🥚疼

    其实就是最近在玩 Spring 新出的 JdbcClient ( JdbcTemplate 的封装版),感觉在 Java 有多行字符串后,在 Java 代码里写 SQL 完全不是什么问题,而且也不用使用难用的 XML 去定义 resultMap (直接在 Java 里定义 record 或者 class 然后用构造器就可以了)

    public record User(Long id, String name, Integer sex) {
    }
    
    @GetMapping("/users/in")
    public Iterable<User> listInIds(@RequestParam List<Integer> ids) {
        return jdbcClient.sql("""
                SELECT *
                FROM `user`
                WHERE `id` IN (:ids)
                """)
                .param("ids", ids)
                .query(User.class)
                .list();
    }
    

    但是在碰到动态条件的 where 语句的时候,在 Java 代码里手搓 SQL 看着也很让人头大……这时候 MyBatis 提供的 dynamic SQL 就很好用了

    但真的不喜欢 XML……

    MyBatis-Plus 也了解过,但说不上来为什么,总是感觉不太喜欢这个库……

    155 条回复    2024-01-04 01:52:02 +08:00
    1  2  
    hefish
        1
    hefish  
       309 天前   ❤️ 4
    我一直喜欢写规范的 SQL ,奈何前些年 ORM 更流行。
    programMrxu
        2
    programMrxu  
       309 天前
    比较喜欢 orm ,
    ashuai
        3
    ashuai  
       309 天前
    投 SQL92 一票。
    小项目怎么顺手怎么来。
    大项目特别是有性能要求的,ORM hold 不 hold 得住先?
    potatowish
        4
    potatowish  
       309 天前 via iPhone
    首先,MyBatis 配置开启驼峰命名映射时,也不用写 resultMap ,在 MBP 中也是默认开启的。

    个人的话简单项目用 JPA ,复杂项目用 MBP 。不讨厌 XML ,更喜欢原生的 SQL 。
    liuhan907
        5
    liuhan907  
       309 天前   ❤️ 1
    我个人更喜欢 ORM ,但我是写 C# 的。
    xiaoxinTOm
        6
    xiaoxinTOm  
       309 天前
    有些比较复杂的 sql 要写简直要死,我 sql 写不好,有些需求完全没有思虑,现在用 gpt 写
    chendy
        7
    chendy  
       309 天前   ❤️ 1
    都用,简单的 orm ,复杂的 sql
    just1
        8
    just1  
       309 天前
    喜欢手写 sql ,但是代码里如果有变量还是 orm 。python 有啥好用的 orm
    XCFOX
        9
    XCFOX  
       309 天前   ❤️ 15
    据我观察,大部分 Java 和 Go 开发者对 ORM 无感甚至讨厌 ORM ;而大部分 C#、Node.js 、Ruby 开发者喜欢用 ORM 。
    原因其实很简单,C# 的 EF Core 、Node.js 的 Prisma, MikroOrm 、Ruby 的 ActiveRecord 很好用。

    一款好的 ORM 应该尽可能提供该语言原生的写法,提供完善的类型安全、提供灵活的 Query Builder 以应对尽量多的 SQL 语法。

    Java/Go 生态内缺少用起来顺手的 ORM 。要是 Java 有 EF Core 、Go 有 Prisma ,我相信所有人都会喜欢 ORM 。
    lilichen
        10
    lilichen  
       309 天前
    C#, ORM
    taotaodaddy
        11
    taotaodaddy  
       309 天前   ❤️ 1
    @just1 我用 python 的 peewee,感觉还可以
    QlanQ
        12
    QlanQ  
       309 天前
    orm 好用的多,特别是那种关联关系
    手写 sql ,如果在后续需求中,需要加入软删除,是不是每个 sql 都要检查,包括链表查询
    还有一对多和多对多,后续调整的时候,如果手写这种 sql ,是不是差不多项目要重构了?如果用 orm 的话,就简单很多了
    有说如果 sql 很复杂,orm 的性能跟不上,可能我代码写的少了,我并没有遇到 sql 很复杂的情况,如果 sql 很复杂多链表的情况,一般都是 分成多个简单的 sql ,然后用程序处理的吧
    xuld
        13
    xuld  
       309 天前
    这是我设计的内置 sql 的语法:
    return db.queryAll(User -> u where ids.contains(u.id) orderby u.createBy desc select u.id, u.name)
    gam2046
        14
    gam2046  
       309 天前
    不确定我理解的对不对。ORM 主要解决的是编程语言数据类型与数据库类型不一致,进而实现了,切换数据库而不用修改代码的结果。

    但是这种结果在现实条件里太少了,没有人会无聊了换数据库玩。

    那么回到语言类型与数据库类型不一致的问题上来,其实自己解决也并没有多麻烦,特别是现在许多数据库支持一些非简单类型的数据,(例如 JSON/Blob 等等),对于这些类型,ORM 反而支持的不太好,还不如自己手写。

    所以现阶段来看,我粗浅的认为,ORM 并不是必须的(也就是说并没有解决什么实质上的问题),依据个人习惯来好了。手搓 SQL 更能控制 SQL 语句的质量与规模。我想没几个项目从头至尾都是简单的单表查询吧,多表查询,ORM 生成的语句质量,一般也就是个中规中矩,能用的水平。
    jjww
        15
    jjww  
       309 天前
    c#, 看场景吧.
    一般情况下 EF Core 搞定.
    二般情况比如用 timescaledb 的时候就 dbup + 手写迁移文件.
    seth19960929
        16
    seth19960929  
       309 天前 via Android
    肯定 ORM , 我还是无法理解动态 SQL 怎么用原生好写?难不成自己封装一个类优雅的组装, 结果只有自己会用,到头来就是不肯用开源的呗?
    StoneHuLu
        17
    StoneHuLu  
       309 天前
    我写 c#,我用 freeSql 的,ef 我觉得太重了,freeSql 主要是比较灵活,想 orm 就 orm ,想 sql 就 sql ,里面直接一个 ado 拿出来,想咋用就咋用,配置也很简单,各种 aop 功能方便调试
    changdy
        18
    changdy  
       309 天前
    @gam2046 现在数据库之间的差异 太大了.已经不是 orm 能弥补得了.

    对于日常两三张表 join 以上的情况 只有手写 sql.
    如果日常不 join 表 那肯定可以用 orm.
    sephiroka
        19
    sephiroka  
       309 天前
    肯定是都用啊
    Features
        20
    Features  
       309 天前   ❤️ 19
    PHP 的 ORM 天下第一
    idealhs
        21
    idealhs  
       309 天前
    JAVA 里如果有 EF Core 就不会有 ORM 好不好用这个问题出现了
    woodfizky
        22
    woodfizky  
       309 天前
    我只知道原生 SQL 防 SQL 注入很麻烦,特别是自己拼的原生 SQL 。而如果你自己做防注入了,又很像在干 ORM 该干的事情。

    ORM 的话,因为我写 python ,公司的项目用的 SQLAlchemy+FastAPI+Gino ,稍微有点学习成本,有些写法文档也没介绍,会有隐藏的坑,但是熟悉之后写起来还是挺舒服的。

    性能肯定是原生好,因为 ORM 除了负责把代码对象变成 SQL 语句去执行,还要把查询结果又加载成代码对象,写起来是很舒服,但是中间的转换是有代价的。
    6167
        23
    6167  
       309 天前   ❤️ 1
    python+sqlalchemy ,非常好用,三四张表 join 起来没什么问题
    wangkun025
        24
    wangkun025  
       309 天前
    rubiest ,必然是 ORM 啊。
    lyxxxh2
        25
    lyxxxh2  
       309 天前
    工作 5 年了 只用 orm
    没有 orm 完成不了的 sql
    musi
        26
    musi  
       309 天前
    前端,喜欢 orm ,但是写 go 发现没有一个 orm 是好用的。。。
    coinbase
        27
    coinbase  
       309 天前
    复杂的用 SQL, 简单的逻辑判断用 ORM 更方便
    cheng6563
        28
    cheng6563  
       309 天前
    简单 CURD 用 ORM ,复杂查询写 SQL (比如连表或者用了 OR )
    twofox
        29
    twofox  
       309 天前
    歪个楼,Java 21 的字符模板真的好丑陋
    skyworker
        30
    skyworker  
       309 天前   ❤️ 2
    @Features 确切说, 是 Eloquent 天下第一
    eliot121450375
        31
    eliot121450375  
       309 天前
    @woodfizky alchemy2.0 自身也有对异步的支持,为啥要用 gino 呢?我没接触过 gino
    woodfizky
        32
    woodfizky  
       309 天前
    @eliot121450375 可以说是遗留问题了。。当时还用的是 SQLAlchemy1.3 ,那时候还不支持异步。
    不过 Gino 可以兼容 SQLAlchemy 的语法,加上连接池用的也是 Gino 的,就这么用下来了。
    coinbase
        33
    coinbase  
       309 天前
    --portfolio
    WITH all_transfers AS (
    SELECT "from", "to", token_address, -value AS value_diff
    FROM erc20_transfers_from_shard
    WHERE "from" = LOWER('0x9B1bbecdf6409ff6F7cAE9DA2C4d2C7f6b8CF9E9')
    UNION ALL
    SELECT "from", "to", token_address, value AS value_diff
    FROM erc20_transfers_to_shard
    WHERE "to" = LOWER('0x9B1bbecdf6409ff6F7cAE9DA2C4d2C7f6b8CF9E9')
    ),
    sum_transfer AS (
    SELECT token_address, SUM(value_diff) AS sum_value
    FROM all_transfers
    GROUP BY token_address
    ),
    price_usd_token AS (
    SELECT sum_transfer.token_address, sum_transfer.sum_value, tokens.price_usd, tokens.decimals, tokens.symbol,
    (tokens.price_usd * sum_transfer.sum_value) / POWER(10, tokens.decimals) AS total_value
    FROM sum_transfer
    INNER JOIN tokens ON tokens.address = sum_transfer.token_address
    WHERE tokens.decimals != 0 AND tokens.decimals IS NOT NULL AND tokens.is_honeypot = false
    )
    SELECT token_address, symbol, sum_value, total_value, price_usd
    FROM price_usd_token
    WHERE total_value IS NOT NULL AND total_value > 0
    ORDER BY total_value DESC;


    复杂的还是 SQL 舒服
    jtsai
        34
    jtsai  
       309 天前
    SQL ,ORM 把简单的问题搞复杂了
    codingmiao
        35
    codingmiao  
       309 天前
    混着用,现在的 ORM 框架还配有代码生成器,传个表名进去一波帮你生成到前端 crud 界面了,还是很省心的。但是复杂业务用 ORM 就有点多余了。
    zhhqiang
        36
    zhhqiang  
       309 天前
    ORM 对一些业务处理很方便 sql 也很重要
    monkeyWie
        37
    monkeyWie  
       309 天前
    那些说喜欢 ORM 的来,多表链接 + 多个子查询 + 聚合查询 + 动态条件,用 ORM 给我写个看看
    jiayouzl
        38
    jiayouzl  
       309 天前
    肯定 Orm 啊,后期维护都简单很多,纯 Sql 语句后期维护太麻烦了。
    encro
        39
    encro  
       309 天前
    @just1

    python 不是只有 3 个嘛,django,sqlalchemy,Peewee
    flyingfz
        40
    flyingfz  
       309 天前
    原来用 C# 的时候,用过 Stack Overflow 开源的 dapper , 用 C#的 强烈推荐 这个库。

    现在基本是手写 sql .
    事务控制 、 复杂 SQL 等场景, 还是手写舒服。 防注入的话,不要拼接客户端的内容,查询用参数就 OK 了。
    dobelee
        41
    dobelee  
       309 天前
    @monkeyWie 大点的业务一般都不让连表和聚合。ORM 的优势正是动态条件,几十个条件拼接,完全不用考虑语法错误,SQL 拼接会死人的。
    NoobNoob030
        42
    NoobNoob030  
       309 天前   ❤️ 1
    php 的 orm 用着比 java 的爽多了
    zhengwenk
        43
    zhengwenk  
       309 天前
    自己做的小项目喜欢直接 sql 。 其他 orm
    Sigrdirfa
        44
    Sigrdirfa  
       309 天前 via Android
    自己写喜欢写 SQL ,但是代码里看到同事的 SQL 就会想死....那还是大家一起用 ORM 吧。
    gongquanlin
        45
    gongquanlin  
       309 天前
    laravel 的 orm 会对一些联表之类的查询进行优化,比如批量的一对多的子查询,laravel 会先把所有 id 查出来,然后再根据 id 把所有的子数据查出来再聚合,基本上就是 n + 1 条请求就解决了;
    但是 mybatis 即使映射了 association 和 id ,也是会循环查 id ,再循环查子数据

    当时从 php 转 java 的时候发现,phper 如此牛逼和人性化,java 如此落后。奈何国内潮流是 Java

    直到我发现了 nodejs ,哈哈~
    deadlyn
        46
    deadlyn  
       309 天前
    @gam2046 Confluence 后端就是大量 ORM ,涉及各种表关联都必须精心维护好 Entity ,这类产品有一个特色是卖给不同的客户群体,可支持不同的 DB
    sunmoon1983
        47
    sunmoon1983  
       309 天前   ❤️ 6
    vialon17
        48
    vialon17  
       309 天前
    直接手搓 sql ,别人也能看得懂,
    复杂的逻辑可以取完值后再做逻辑运算。
    hongye
        49
    hongye  
       309 天前
    最近在做信创迁移,A 系统中存在大段手写的 MySQL 方言,B 系统基本上使用的都是 mybatis 框架实现的( SQL 标准兼容比较好)。两个系统的迁移成本估计为 5:1 ,因此从可维护性角度还是建议采用 ORM 框架
    flmn
        50
    flmn  
       309 天前
    go 的 ent 谁用过,介绍介绍经验
    gitrebase
        51
    gitrebase  
    OP
       309 天前
    @sunmoon1983 这🫥啥啊
    jurassic2long
        52
    jurassic2long  
       309 天前
    @sunmoon1983 以前接手过这种项目, 当时就想把写这种 SQL 的人拉出去砍了
    bianhui
        53
    bianhui  
       309 天前   ❤️ 2
    @hongye 那明显是 A 好啊。要是都得 A 至少有多四个人有活干,养活一家老小。你可能只是用一个简简单单的 orm 框架,未来有四个人因为你的这一举动而失业,换不起房贷,老婆和别人跑了,3 个还不是自己的,收手吧
    lifei6671
        54
    lifei6671  
       309 天前
    @XCFOX 我用 gorm ,感觉挺好用的,生成的 SQL 基本上和手写 SQL 差不多。还有很多灵活的表达式写法。
    CloveAndCurrant
        55
    CloveAndCurrant  
       309 天前
    @flmn 用过,还行,感觉比 gorm 好用,就是生成的 SQL 很垃圾,强制加 distinct ,不知道最新版改了没有
    ntedshen
        56
    ntedshen  
       309 天前
    与其说 sql 好用不如说是 java/go 系的 orm 不够好用。。。
    尝试写过 go 的 orm 。。。那时候泛型还没出,建个模型自己写都写的头大,背起来更是蛋疼,那可不是 sql 好用嘛。。。

    可能弱类型对这块有先天优势?
    至少 nodejs 和 php 的 orm 确实很好用,非要写一堆 join 和专有语法也可以自己 mod ,至于性能影响。。。拼个 sql 能有性能影响你就不该上弱类型。。。
    Binwalker
        57
    Binwalker  
       309 天前
    目前我感觉没有 ORM 的体验能和 Rails 的 ActiveRecord 相媲美
    yule111222
        58
    yule111222  
       309 天前
    不存在真正的 ORM 框架,因为这里面的 M 通常是对应数据库表的 entity ,这种模型压根做不了业务
    另外我用 kotlin 和 KTORM 还是挺爽的
    XML 里写 sql 是最丑的
    gitrebase
        59
    gitrebase  
    OP
       309 天前
    @lifei6671 我也喜欢用 GORM ,不可否认的是 GORM 确实很不优雅、很不 ORM ,但是感觉……他做到了便携性与灵活性的一个 balance……很怪,我个人也觉得 GORM 丑不垃圾的,但感觉真的很好用
    coinbase
        60
    coinbase  
       309 天前
    gitrebase
        61
    gitrebase  
    OP
       309 天前
    @yule111222 羡慕 Kotlin ,只能私下玩玩 Kotlin ;我就是因为 XML 才很不想用 MyBatis……太丑陋了,但在 dynamic where conditions 上 MyBatis 又挺好用的……(与 JdbcTemplate 相比)
    IIInsomnia
        62
    IIInsomnia  
       309 天前
    @musi ent
    label
        63
    label  
       309 天前   ❤️ 1
    MyBatis-Plus 的函数式查询条件, 非常好用, 字段名没有硬编码
    jadeborner
        64
    jadeborner  
       309 天前
    肯定 ORM 啊,我们这程序也不止支持一种数据库
    waltcow
        65
    waltcow  
       309 天前
    go 下用着 Ent, 写起来很 fluent
    devilweime
        66
    devilweime  
       309 天前
    java 开发,混用,单表 ORM ;联表 SQL
    Uplay
        67
    Uplay  
       309 天前
    @sunmoon1983 #47 逻辑能力太强了
    jadeborner
        68
    jadeborner  
       309 天前
    @monkeyWie 大脑一根筋吗?用了 ORM 就不能手写 sql 了?什么场景用什么方法。
    shellcodecow
        69
    shellcodecow  
       309 天前
    go 用 gorm
    monkeyWie
        70
    monkeyWie  
       309 天前
    @jadeborner #68 有没有可能是有人只用 ORM 不手写 sql 呢,反正不是我
    skywalkerfc
        71
    skywalkerfc  
       309 天前
    写过 PHP 、Go 、Python:
    PHP 的大框架 orm 最好用,用起来很丝滑。
    GO 用过 xorm 和 gorm ,现在简单的用 gorm ,复杂的写原生 sql 。
    Python 现在 SQLAlchemy ,复杂的基本都能 hold 住。
    stevenshuang
        72
    stevenshuang  
       309 天前 via iPhone
    @sunmoon1983 这条 sql 是不是直接保住了饭碗,没人敢动🐮
    aLazarus
        73
    aLazarus  
       309 天前
    公司的项目需要适配至少 7 个数据库,尽管各家数据库都支持标准 sql 语句,但业务逻辑没有那么简单,所以还是会使用 orm
    miaotaizi
        74
    miaotaizi  
       309 天前
    能用 ORM 的地方 别用 SQL 就行了

    ORM 更多的还是为了表达业务逻辑, 毕竟编辑器里面搜变量的 赋值/读取 还是很方便的

    拼出来的 SQL 我觉得是没法维护的
    lerosua
        75
    lerosua  
       309 天前
    手写 SQL ,水平不行,还可能被注入~ 能 ORM 就 ORM
    Govda
        76
    Govda  
       309 天前
    ORM 实现不了、性能过低才考虑 SQL
    gaocc
        77
    gaocc  
       309 天前
    前端人员用 nestjs 写后端,用 typeorm ,复杂 sql 用 sql
    dif
        78
    dif  
       309 天前
    看业务,orm 优先。
    chenqh
        79
    chenqh  
       309 天前
    @monkeyWie 关键是动态查询 orm 比较好做吧.像管理后台,一个用户列表或者订单列表,框框就是高达 10 个动态查询,sql
    完全想不出来应该怎么弄. 至于 sql,我也只会简单 sql 啊.orm 最主要的问题可能就是两张表,都有字段要查的话,我不知道怎么做,因为我表设计的时候,基本只查一张表.很多时候甚至会把两张表合成一张表.虽然最佳实践肯定不是这样的,但是
    做起来简单啊.最关键是并发不大
    magicZ
        80
    magicZ  
       309 天前
    我们查询的报表 sql 一堆函数和嵌套,orm 不太适合这种场合
    yidinghe
        81
    yidinghe  
       309 天前
    不要在意项目大小,小项目最终也会演化出大量的关联查询。对 SQL 本身的封装要好过 ORM 。
    woodfizky
        82
    woodfizky  
       309 天前
    还真可以,其他 ORM 不熟不知道,python + SQLAlchemy 完全可以做到 join + sub_query + union_query + group_by + 动态传入 and 、or 条件,写熟悉了跟写原生 SQL 的思路是差不多的
    yooomu
        83
    yooomu  
       309 天前
    我工作写 java 的,日常用 mybatis plus ,像 JPA 那种 ORM 还是用不来,黑箱太多了,有种不安全感。还是根据场景来吧,简单的单表会用 mybatis plus 的 CRUD 接口,涉及联表还是手写 SQL 比较舒服,清晰明了,别人理解起来也容易。把联表拆成多个单表查询,然后用 mybatis plus 其实也可以,出现问题也方便调试,但是代码量太大了,写起来一大坨,别人也不好理解
    Seulgi
        84
    Seulgi  
       309 天前
    表设计好,orm 当然效率更高。表设计差,当然 sql 更好写。
    BuffDog
        85
    BuffDog  
       309 天前
    以前写 C#用 SqlSugar ,真的神中神,目前没见过能超越这个的 ORM
    Linq 写 SQL ,爽的不行
    chimission
        86
    chimission  
       309 天前
    这个问题和具体的语言关系还是蛮大的, 像 python 的 peewee ,orm 写起了思维方式和原生的 sql 基本一致,用的时候很少遇到需要手写 sql 的情况,但是写 GO 的时候就没这么顺滑了,还要把脑子里的 sql 转义成 orm 的语法才能写下来
    memorycancel
        87
    memorycancel  
       309 天前
    用过 Ruby 的 ActiveRecord 后,你就会发现,在座的各位都是。。。
    kakki
        88
    kakki  
       309 天前
    Rails +1 ,Java 和 Go ,属于语言限制了 ORM 的发挥,元编程能力越强,ORM 越强。
    Corrots
        89
    Corrots  
       309 天前
    Go 之前有个新项目用过 Gorm ,但是体验不是很好,遇到过几个小坑,官方的文档也很久没更新过了。
    后面就只用 sql builder: Squirrel 或者直接写 SQL 了
    huijiewei
        90
    huijiewei  
       309 天前
    以前喜歡寫存儲過程和 SQL

    現在喜歡 ORM
    illusory
        91
    illusory  
       309 天前
    静态语言的强大 ORM ,虽然它自称 Functional Relational Mapping (FRM)

    https://scala-slick.org/doc/3.0.0/introduction.html
    wenxueywx
        92
    wenxueywx  
       309 天前
    什么方便用什么;
    什么用的熟练用什么;
    原生 sql 写起是非常爽,奈何处理业务逻辑有时候反而更麻烦。这时候就该 orm 上场了。
    sheeta
        93
    sheeta  
       309 天前
    建议写 Java 的都来看看 PHP 的 ORM ,哈哈哈 https://laravel.com/docs/10.x/queries
    Chad0000
        94
    Chad0000  
       309 天前
    C#,EF Core 确实 NB ,但我现在倾向于使用轻量极 ORM 了:因为我在推独立服务。而且之前有次 EF Core 升级搞出很多问题,我觉得服务需要确定性所以在尽量减少 EF Core 的使用了。
    JaguarJack
        95
    JaguarJack  
       309 天前
    Eloquent ORM:在座的各位都是辣鸡
    q447643445
        97
    q447643445  
       309 天前
    一开始 只写 sql
    后来 混用
    现在 只用 orm
    业务简单 已经很多个项目 不写 sql 了 太舒服了
    mmmhhhddd
        98
    mmmhhhddd  
       309 天前
    不考虑性能只追求方便 orm, 复杂查询和性能追求原生 sql
    guotie
        99
    guotie  
       309 天前
    drizzle 的 orm 我觉得很好
    fancy2020
        100
    fancy2020  
       309 天前
    ORM 封装太重,裸写 SQL 太麻烦坑也太多,最喜欢的是 knex.js 这种 SQL builder ,以及 objection.js
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2834 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 14:31 · PVG 22:31 · LAX 07:31 · JFK 10:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.