c# - Clean Code: Readable Dependency Injection suggestions? -
i have project adds elements autocad drawing. noticed starting write same ten lines of code in multiple methods (only showing 2 simplicity).
initial implementation: notice thing changes adding line instead of circle.
[commandmethod("test", commandflags.session)] public void test() { addlinetodrawing(); addcircletodrawing(); } private void addlinetodrawing() { using (documentlock lockeddocument = application.documentmanager.mdiactivedocument.lockdocument()) { using (database database = application.documentmanager.mdiactivedocument.database) { using (transaction transaction = database.transactionmanager.starttransaction())//start transaction { //open block table read blocktable blocktable = transaction.getobject(database.blocktableid, openmode.forread) blocktable; //open block table record model space write blocktablerecord blocktablerecord = (blocktablerecord)transaction.getobject(blocktable[blocktablerecord.modelspace], openmode.forwrite); line line = new line(new point3d(0, 0, 0), new point3d(10, 10, 0)); blocktablerecord.appendentity(line); transaction.addnewlycreateddbobject(line, true); transaction.commit(); } } } } private void addcircletodrawing() { using (documentlock lockeddocument = application.documentmanager.mdiactivedocument.lockdocument()) { using (database database = application.documentmanager.mdiactivedocument.database) { using (transaction transaction = database.transactionmanager.starttransaction())//start transaction { //open block table read blocktable blocktable = transaction.getobject(database.blocktableid, openmode.forread) blocktable; //open block table record model space write blocktablerecord blocktablerecord = (blocktablerecord)transaction.getobject(blocktable[blocktablerecord.modelspace], openmode.forwrite); circle circle = new circle(new point3d(0, 0, 0), new vector3d(0, 0, 0), 10); blocktablerecord.appendentity(circle); transaction.addnewlycreateddbobject(circle, true); transaction.commit(); } } } }
injection: approached removed duplication of code, think readability poor.
[commandmethod("test", commandflags.session)] public void test() { performactiononblocktable(new circledrawer()); performactiononblocktable(new linedrawer()); } public interface idraw { dbobject drawobject(blocktablerecord blocktablerecord); } public class circledrawer : idraw { public dbobject drawobject(blocktablerecord blocktablerecord) { circle circle = new circle(new point3d(0, 0, 0), new vector3d(0, 0, 0), 10); blocktablerecord.appendentity(circle); return circle; } } public class linedrawer : idraw { public dbobject drawobject(blocktablerecord blocktablerecord) { line line = new line(new point3d(0, 0, 0), new point3d(10, 10, 0)); blocktablerecord.appendentity(line); return line; } } private void performactiononblocktable(idraw drawer) { using (documentlock lockeddocument = application.documentmanager.mdiactivedocument.lockdocument()) { using (database database = application.documentmanager.mdiactivedocument.database) { using (transaction transaction = database.transactionmanager.starttransaction())//start transaction { //open block table read blocktable blocktable = transaction.getobject(database.blocktableid, openmode.forread) blocktable; //open block table record model space write blocktablerecord blocktablerecord = (blocktablerecord)transaction.getobject(blocktable[blocktablerecord.modelspace], openmode.forwrite); dbobject newobject = drawer.drawobject(blocktablerecord); transaction.addnewlycreateddbobject(newobject, true); transaction.commit(); } } } }
injecting func<>: seemed give me similar result, better readability.
[commandmethod("test", commandflags.session)] public void test() { performactiononblocktable(addlinetodrawing); performactiononblocktable(addcircletodrawing); } private void performactiononblocktable(func<blocktablerecord, dbobject> action) { using (documentlock lockeddocument = application.documentmanager.mdiactivedocument.lockdocument()) { using (database database = application.documentmanager.mdiactivedocument.database) { using (transaction transaction = database.transactionmanager.starttransaction())//start transaction { //open block table read blocktable blocktable = transaction.getobject(database.blocktableid, openmode.forread) blocktable; //open block table record model space write blocktablerecord blocktablerecord = (blocktablerecord)transaction.getobject(blocktable[blocktablerecord.modelspace], openmode.forwrite); dbobject newobject = action(blocktablerecord); transaction.addnewlycreateddbobject(newobject, true); transaction.commit(); } } } } private dbobject addlinetodrawing(blocktablerecord blocktablerecord) { line line = new line(new point3d(0, 0, 0), new point3d(10, 10, 0)); blocktablerecord.appendentity(line); return line; } private dbobject addcircletodrawing(blocktablerecord blocktablerecord) { circle circle = new circle(new point3d(0, 0, 0), new vector3d(0, 0, 0), 10); blocktablerecord.appendentity(circle); return circle; }
i can have not done di, i'm quite new this. of more experienced developers give me pro's/con's of 2 different approaches? there in last approach that's red flag? seems more readable second approach. maybe i'm not understanding injection... in advance input!
you simple refactoring instead of options provided:
[commandmethod("test", commandflags.session)] public void test() { addlinetodrawing(); addcircletodrawing(); } private void addlinetodrawing() { createobjectonblocktable( new line(new point3d(0, 0, 0), new point3d(10, 10, 0))); } private void addcircletodrawing() { createobjectonblocktable( new circle(new point3d(0, 0, 0), new vector3d(0, 0, 0), 10)); } private void createobjectonblocktable(dbobject dbobject) { using (var lockeddocument = application.documentmanager.mdiactivedocument.lockdocument()) using (var database = application.documentmanager.mdiactivedocument.database) using (var transaction = database.transactionmanager.starttransaction()) { // open block table read var blocktable = (blocktable)transaction.getobject(database.blocktableid, openmode.forread); // open block table record model space write var blocktablerecord = (blocktablerecord)transaction.getobject(blocktable[blocktablerecord.modelspace], openmode.forwrite); blocktablerecord.appendentity(dbobject); transaction.addnewlycreateddbobject(dbobject, true); transaction.commit(); } }
i think more readable.
update: run special logic, idea of using delegates. i'd refactor code this:
private void createobjectonblocktable(dbobject dbobject) { performactiononblocktable((transaction, blocktablerecord) => { blocktablerecord.appendentity(dbobject); transaction.addnewlycreateddbobject(dbobject, true); }); } private void performactiononblocktable(action<transaction, blocktablerecord> action) { using (var lockeddocument = application.documentmanager.mdiactivedocument.lockdocument()) using (var database = application.documentmanager.mdiactivedocument.database) using (var transaction = database.transactionmanager.starttransaction()) { // open block table read var blocktable = (blocktable)transaction.getobject(database.blocktableid, openmode.forread); // open block table record model space write var blocktablerecord = (blocktablerecord)transaction.getobject(blocktable[blocktablerecord.modelspace], openmode.forwrite); // run specific logic action(transaction, blocktablerecord); transaction.commit(); } }
(the rest of code same)
performactiononblocktable
can reused run arbitrary logic using transaction , block table record.
Comments
Post a Comment