Retour à la simplicité
-
Upload
montreal-jug -
Category
Education
-
view
482 -
download
3
Transcript of Retour à la simplicité
Retour à la simplicité
Vincent Tencé@testinfected
http://vtence.comhttp://github.com/testinfected
Un sentiment de déja-vu ?
Vous démarrez un projet en assemblant 5-10+ librairies et frameworks
Le bagage à trainer est lourd et coûteux
Un des frameworks se met en travers de votre chemin
Vous vous sentez prisonnier de ce framework
Un framework vous surprend par sa « magie »
Faisons simple !
• Une option sans doute ignorée par biais de :
1. temps
2. sophistication
3. analyse
Le point de départ
• Application à vocation académique, développée avec :
• Spring et Spring MVC
• Hibernate, JPA
• Maven
• Velocity et SiteMesh
• 53 jars externes !
Le défi
• Uniquement des outils simples
• DIYS (Do It Yourself Simply)
• Assemblage, déploiement et configuration faciles
• XML
• Annotations
• Framework (Web, ORM, DI)
Buildr
define 'petstore', [..] do define 'domain' do compile.with test.with HAMCREST package :jar end
define 'persistence' do compile.with project(:domain) test.with HAMCREST, :flyway, :mysql, NO_LOG, [...] package :jar end
define 'webapp' domain compile.with :simpleframework, :jmustache, [...] test.with HAMCREST, :antlr_runtime, :cssselectors, :hamcrest_dom, [...] test.with transitive(artifacts(:nekohtml, :htmlunit, :jmock_legacy))
package :jar end
new
AttachmentStorage attachments = new FileSystemPhotoStore("/photos");Cart cart = new SessionScope(request.session()).cart();Connection connection = new ConnectionReference(request).get();Transactor transactor = new JDBCTransactor(connection);ProductCatalog catalog = new ProductsDatabase(connection);ItemInventory inventory = new ItemsDatabase(connection);OrderBook orders = new OrdersDatabase(connection);
ProcurementRequestHandler procurement = new PurchasingAgent(catalog, inventory, transactor);
OrderNumberSequence orderNumbers = new OrderNumberDatabaseSequence(connection);Cashier cashier = new Cashier(orderNumbers, orders, inventory, cart, transactor);
Routing
Routes routes = Routes.draw(new Router() {{ get("/products").to(new ListProducts(catalog, attachments, pages.products())); post("/products").to(new CreateProduct(procurement)); get("/products/:product/items").to(new ListItems(inventory, pages.items())); post("/products/:product/items").to(new CreateItem(procurement)); get("/cart").to(new ShowCart(cashier, pages.cart())); post("/cart").to(new CreateCartItem(cashier)); get("/orders/new").to(new Checkout(cashier, pages.checkout())); get("/orders/:number").to(new ShowOrder(orders, pages.order())); post("/orders").to(new PlaceOrder(cashier)); delete("/logout").to(new Logout()); map("/").to(new StaticPage(pages.home()));}});
MVC
public class ShowOrder implements Application { private final OrderBook orderBook; private final Page orderPage;
public ShowOrder(OrderBook orderBook, Page orderPage) { this.orderBook = orderBook; this.orderPage = orderPage; }
public void handle(Request request, Response response) throws Exception { String number = request.parameter("number"); Order order = orderBook.find(new OrderNumber(number)); orderPage.render(response, context().with("order", order).asMap()); }}
Data Mapping
public class OrdersDatabase implements OrderBook { private final Connection connection; [...]
public OrdersDatabase(Connection connection) { this.connection = connection; }
private List<LineItem> findLineItemsOf(Order order) { return Select.from(lineItems). where("order_id = ?", idOf(order).get()). orderBy("order_line"). list(connection); }
private Order findOrder(OrderNumber orderNumber) { return Select.from(orders, "_order"). leftJoin(payments, "payment", "_order.payment_id = payment.id"). where("_order.number = ?", orderNumber). first(connection); }
Transactions
public class Cashier implements SalesAssistant { [...]
public OrderNumber placeOrder(PaymentMethod paymentMethod) throws Exception { QueryUnitOfWork<OrderNumber> order = new QueryUnitOfWork<OrderNumber>() { public OrderNumber query() throws Exception { OrderNumber nextNumber = orderNumberSequence.nextOrderNumber(); final Order order = new Order(nextNumber); order.addItemsFrom(cart); order.pay(paymentMethod); orderBook.record(order); cart.clear(); return nextNumber; } }; return transactor.performQuery(order); }
Toutefois
• Pas très « entreprise »
• Pas à la portée de toutes les équipes
• Pas à toutes les sauces
• Pas sans risque
Leçons apprises
• Éviter la tentation des frameworks
• Utiliser des outils simples, légers et spécialisés
• Construire mes propres outils
• S’inspirer des meilleures idées; réécrire le code simplement
• Spécialiser plutôt que de généraliser
Références
•Nouvelle version :https://github.com/testinfected/simple-petstore
• Ancienne version :https://github.com/testinfected/petstore
• Data Mapping :https://github.com/testinfected/tape
•Web :https://github.com/testinfected/molecule